|
|
1.1 root 1: /*
2: * GRUB -- GRand Unified Bootloader
3: * Copyright (c) 2000, 2001 Free Software Foundation, Inc.
4: * Copyright (c) 2005 Rink Springer
5: *
6: * This file is based on FreeBSD 5.4-RELEASE's /sys/boot/common/ufsread.c,
7: * and has some minor patches so it'll work with Cromwell/GRUB.
8: *
9: */
10: /*-
11: * Copyright (c) 2002 McAfee, Inc.
12: * All rights reserved.
13: *
14: * This software was developed for the FreeBSD Project by Marshall
15: * Kirk McKusick and McAfee Research,, the Security Research Division of
16: * McAfee, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as
17: * part of the DARPA CHATS research program
18: *
19: * Redistribution and use in source and binary forms, with or without
20: * modification, are permitted provided that the following conditions
21: * are met:
22: * 1. Redistributions of source code must retain the above copyright
23: * notice, this list of conditions and the following disclaimer.
24: * 2. Redistributions in binary form must reproduce the above copyright
25: * notice, this list of conditions and the following disclaimer in the
26: * documentation and/or other materials provided with the distribution.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38: * SUCH DAMAGE.
39: */
40: /*-
41: * Copyright (c) 1998 Robert Nordier
42: * All rights reserved.
43: *
44: * Redistribution and use in source and binary forms are freely
45: * permitted provided that the above copyright notice and this
46: * paragraph and the following disclaimer are duplicated in all
47: * such forms.
48: *
49: * This software is provided "AS IS" and without any express or
50: * implied warranties, including, without limitation, the implied
51: * warranties of merchantability and fitness for a particular
52: * purpose.
53: */
54: #ifdef FSYS_UFS
55:
56: #include "asm/types.h"
57:
58: #include "shared.h"
59: #include "filesys.h"
60:
61: #include "ufs_dinode.h"
62: #include "ufs_fs.h"
63:
64: #ifdef __i386__
65: /* XXX: Revert to old (broken for over 1.5Tb filesystems) version of cgbase
66: (see sys/ufs/ffs/fs.h rev 1.39) so that i386 boot loader (boot2) can
67: support both UFS1 and UFS2 again. */
68: #undef cgbase
69: #define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c)))
70: #endif
71:
72: /*
73: * We use 4k `virtual' blocks for filesystem data, whatever the actual
74: * filesystem block size. FFS blocks are always a multiple of 4k.
75: */
76: #define VBLKSHIFT 12
77: #define VBLKSIZE (1 << VBLKSHIFT)
78: #define VBLKMASK (VBLKSIZE - 1)
79: #define DBPERVBLK (VBLKSIZE / DEV_BSIZE)
80: #define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize >> VBLKSHIFT))
81: #define IPERVBLK(fs) (INOPB(fs) / ((fs)->fs_bsize >> VBLKSHIFT))
82: #define INO_TO_VBA(fs, ipervblk, x) \
83: (fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \
84: (((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK))
85: #define INO_TO_VBO(ipervblk, x) ((x) % ipervblk)
86: #define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \
87: ((off) / VBLKSIZE) * DBPERVBLK)
88: #define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
89:
90: /* Buffers that must not span a 64k boundary. */
91: struct dmadat {
92: char blkbuf[VBLKSIZE]; /* filesystem blocks */
93: char indbuf[VBLKSIZE]; /* indir blocks */
94: char sbbuf[SBLOCKSIZE]; /* superblock */
95: char secbuf[DEV_BSIZE]; /* for MBR/disklabel */
96: };
97: static struct dmadat *dmadat = (struct dmadat*)FSYS_BUF;
98:
99: #define SUPERBLOCK ((struct fs*)dmadat->sbbuf)
100:
101: ino_t lookup(const char *);
102: ssize_t fsread(ino_t, void *, size_t);
103:
104: static int dsk_meta;
105: static uint32_t fs_off;
106: static ino_t cur_ino = 0;
107:
108: static inline int
109: dskread (void* buf, unsigned lba, unsigned nblk)
110: {
111: return !devread (lba, 0, nblk * DEV_BSIZE, buf) ? -1 : 0;
112: }
113:
114: #if defined(UFS2_ONLY)
115: #define DIP(field) dp2.field
116: #elif defined(UFS1_ONLY)
117: #define DIP(field) dp1.field
118: #else
119: #define DIP(field) fs->fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field
120: #endif
121:
122: static __inline int
123: fsfind(const char *name, ino_t * ino)
124: {
125: char buf[DEV_BSIZE];
126: struct ufs_dirent *d;
127: char *s;
128: ssize_t n;
129: #ifndef UFS2_ONLY
130: static struct ufs1_dinode dp1;
131: #endif
132: #ifndef UFS1_ONLY
133: static struct ufs2_dinode dp2;
134: #endif
135: char* blkbuf = dmadat->blkbuf;
136: struct fs* fs = (struct fs *)dmadat->sbbuf;
137:
138: fs_off = 0;
139: while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0)
140: for (s = buf; s < buf + DEV_BSIZE;) {
141: d = (void *)s;
142: if (!strcmp(name, d->d_name)) {
143: *ino = d->d_fileno;
144:
145: /* below is for grub, which wants the file size
146: */
147: n = IPERVBLK(fs);
148: if (dskread(blkbuf, INO_TO_VBA(fs, n, (*ino)), DBPERVBLK))
149: return -1;
150: n = INO_TO_VBO(n, (*ino));
151: #if defined(UFS1_ONLY)
152: dp1 = ((struct ufs1_dinode *)blkbuf)[n];
153: #elif defined(UFS2_ONLY)
154: dp2 = ((struct ufs2_dinode *)blkbuf)[n];
155: #else
156: if (fs->fs_magic == FS_UFS1_MAGIC)
157: dp1 = ((struct ufs1_dinode *)blkbuf)[n];
158: else
159: dp2 = ((struct ufs2_dinode *)blkbuf)[n];
160: #endif
161:
162: filemax = DIP(di_size);
163: return d->d_type;
164: }
165: s += d->d_reclen;
166: }
167: return 0;
168: }
169:
170: ino_t
171: lookup(const char *path)
172: {
173: char name[MAXNAMLEN + 1];
174: const char *s;
175: ino_t ino;
176: ssize_t n;
177: int dt;
178:
179: ino = ROOTINO;
180: dt = DT_DIR;
181: name[0] = '/';
182: name[1] = '\0';
183: for (;;) {
184: if (*path == '/')
185: path++;
186: if (!*path)
187: break;
188: for (s = path; *s && *s != '/'; s++);
189: if ((n = s - path) > MAXNAMLEN)
190: return 0;
191: memcpy(name, path, n);
192: name[n] = 0;
193: if (dt != DT_DIR) {
194: printk("%s: not a directory.\n", name);
195: return (0);
196: }
197: if ((dt = fsfind(name, &ino)) <= 0)
198: break;
199: path = s;
200: }
201: return dt == DT_REG ? ino : 0;
202: }
203:
204: /*
205: * Possible superblock locations ordered from most to least likely.
206: */
207: static const int sblock_try[] = SBLOCKSEARCH;
208:
209: ssize_t
210: fsread(ino_t inode, void *buf, size_t nbyte)
211: {
212: #ifndef UFS2_ONLY
213: static struct ufs1_dinode dp1;
214: #endif
215: #ifndef UFS1_ONLY
216: static struct ufs2_dinode dp2;
217: #endif
218: static ino_t inomap;
219: char *blkbuf;
220: void *indbuf;
221: struct fs *fs;
222: char *s;
223: size_t n, nb, size, off, vboff;
224: ufs_lbn_t lbn;
225: ufs2_daddr_t addr, vbaddr;
226: static ufs2_daddr_t blkmap, indmap;
227: unsigned int u;
228:
229:
230: blkbuf = dmadat->blkbuf;
231: indbuf = dmadat->indbuf;
232: fs = (struct fs *)dmadat->sbbuf;
233: if (!dsk_meta) {
234: inomap = 0;
235: for (n = 0; sblock_try[n] != -1; n++) {
236: if (dskread(fs, sblock_try[n] / DEV_BSIZE,
237: SBLOCKSIZE / DEV_BSIZE))
238: return -1;
239: if ((
240: #if defined(UFS1_ONLY)
241: fs->fs_magic == FS_UFS1_MAGIC
242: #elif defined(UFS2_ONLY)
243: (fs->fs_magic == FS_UFS2_MAGIC &&
244: fs->fs_sblockloc == sblock_try[n])
245: #else
246: fs->fs_magic == FS_UFS1_MAGIC ||
247: (fs->fs_magic == FS_UFS2_MAGIC &&
248: fs->fs_sblockloc == sblock_try[n])
249: #endif
250: ) &&
251: fs->fs_bsize <= MAXBSIZE &&
252: fs->fs_bsize >= sizeof(struct fs))
253: break;
254: }
255: if (sblock_try[n] == -1) {
256: printk("Not ufs\n");
257: return -1;
258: }
259: dsk_meta++;
260: }
261: if (!inode)
262: return 0;
263: if (inomap != inode) {
264: n = IPERVBLK(fs);
265: if (dskread(blkbuf, INO_TO_VBA(fs, n, inode), DBPERVBLK))
266: return -1;
267: n = INO_TO_VBO(n, inode);
268: #if defined(UFS1_ONLY)
269: dp1 = ((struct ufs1_dinode *)blkbuf)[n];
270: #elif defined(UFS2_ONLY)
271: dp2 = ((struct ufs2_dinode *)blkbuf)[n];
272: #else
273: if (fs->fs_magic == FS_UFS1_MAGIC)
274: dp1 = ((struct ufs1_dinode *)blkbuf)[n];
275: else
276: dp2 = ((struct ufs2_dinode *)blkbuf)[n];
277: #endif
278: inomap = inode;
279: fs_off = 0;
280: blkmap = indmap = 0;
281: }
282: s = buf;
283: size = DIP(di_size);
284: n = size - fs_off;
285: if (nbyte > n)
286: nbyte = n;
287: nb = nbyte;
288: while (nb) {
289: lbn = lblkno(fs, fs_off);
290: off = blkoff(fs, fs_off);
291: if (lbn < NDADDR) {
292: addr = DIP(di_db[lbn]);
293: } else if (lbn < NDADDR + NINDIR(fs)) {
294: n = INDIRPERVBLK(fs);
295: addr = DIP(di_ib[0]);
296: u = (unsigned int)(lbn - NDADDR) / (n * DBPERVBLK);
297: vbaddr = fsbtodb(fs, addr) + u;
298: if (indmap != vbaddr) {
299: if (dskread(indbuf, vbaddr, DBPERVBLK))
300: return -1;
301: indmap = vbaddr;
302: }
303: n = (lbn - NDADDR) & (n - 1);
304: #if defined(UFS1_ONLY)
305: addr = ((ufs1_daddr_t *)indbuf)[n];
306: #elif defined(UFS2_ONLY)
307: addr = ((ufs2_daddr_t *)indbuf)[n];
308: #else
309: if (fs->fs_magic == FS_UFS1_MAGIC)
310: addr = ((ufs1_daddr_t *)indbuf)[n];
311: else
312: addr = ((ufs2_daddr_t *)indbuf)[n];
313: #endif
314: } else {
315: return -1;
316: }
317: vbaddr = fsbtodb(fs, addr) + (off >> VBLKSHIFT) * DBPERVBLK;
318: vboff = off & VBLKMASK;
319: n = sblksize(fs, size, lbn) - (off & ~VBLKMASK);
320: if (n > VBLKSIZE)
321: n = VBLKSIZE;
322: if (blkmap != vbaddr) {
323: if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT))
324: return -1;
325: blkmap = vbaddr;
326: }
327: n -= vboff;
328: if (n > nb)
329: n = nb;
330: memcpy(s, blkbuf + vboff, n);
331: s += n;
332: fs_off += n;
333: nb -= n;
334: }
335: return nbyte;
336: }
337:
338: int
339: ufs_mount (void)
340: {
341: int i, retval = 0;
342:
343: /*
344: * We don't care about stuff being in disklabels or not. If the magic
345: * matches, we're good to go.
346: */
347: for (i = 0; sblock_try[i] != -1; ++i)
348: {
349: if (! (part_length < (sblock_try[i] + (SBLOCKSIZE / DEV_BSIZE))
350: || ! devread (0, sblock_try[i], SBLOCKSIZE, (char *) SUPERBLOCK)))
351: {
352: if (
353: #if defined(UFS1_ONLY)
354: SUPERBLOCK->fs_magic == FS_UFS1_MAGIC
355: #elif defined(UFS2_ONLY)
356: (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC &&
357: SUPERBLOCK->fs_sblockloc == sblock_try[i])
358: #else
359: SUPERBLOCK->fs_magic == FS_UFS1_MAGIC ||
360: (SUPERBLOCK->fs_magic == FS_UFS2_MAGIC &&
361: SUPERBLOCK->fs_sblockloc == sblock_try[i])
362: #endif
363: ) {
364: retval = 1; break;
365: }
366: }
367: }
368: return retval;
369: }
370:
371: int
372: ufs_read (char *buf, int len)
373: {
374: return fsread(cur_ino, buf, len);
375: }
376:
377: int
378: ufs_dir (char *dirname)
379: {
380: cur_ino = lookup(dirname);
381: return cur_ino & 0xffffffff;
382: }
383:
384: int
385: ufs_embed (int* start_sector, int needed_sectors)
386: {
387: /* TODO; unused by Cromwell */
388: return 0;
389: }
390:
391: #endif /* FSYS_UFS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.