903206d120a48942fd67ac91c961911da30b991a
[dragonfly.git] / sys / boot / alpha / boot1 / sys.c
1 /*
2  * Mach Operating System
3  * Copyright (c) 1992, 1991 Carnegie Mellon University
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify and distribute this software and its
7  * documentation is hereby granted, provided that both the copyright
8  * notice and this permission notice appear in all copies of the
9  * software, derivative works or modified versions, and any portions
10  * thereof, and that both notices appear in supporting documentation.
11  *
12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15  *
16  * Carnegie Mellon requests users of this software to return to
17  *
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19  *  School of Computer Science
20  *  Carnegie Mellon University
21  *  Pittsburgh PA 15213-3890
22  *
23  * any improvements or extensions that they make and grant Carnegie Mellon
24  * the rights to redistribute these changes.
25  *
26  *      from: Mach, Revision 2.2  92/04/04  11:36:34  rpd
27  *      fromL Id: sys.c,v 1.21 1997/06/09 05:10:56 bde Exp
28  * $FreeBSD: src/sys/boot/alpha/boot1/sys.c,v 1.4.2.2 2002/01/19 02:16:09 iedowse Exp $
29  * $DragonFly: src/sys/boot/alpha/boot1/Attic/sys.c,v 1.2 2003/06/17 04:28:16 dillon Exp $
30  */
31
32 #include <string.h>
33 #include <sys/param.h>
34 #include <sys/time.h>
35
36 #include <ufs/ffs/fs.h>
37 #include <ufs/ufs/quota.h>
38 #include <ufs/ufs/inode.h>
39
40 #include <sys/dirent.h>
41
42 #define COMPAT_UFS
43
44 struct fs *fs;
45 struct inode inode;
46 int boff = 0;
47
48 /*
49  * We use 4k `virtual' blocks for filesystem data, whatever the actual
50  * filesystem block size. FFS blocks are always a multiple of 4k.
51  */
52 #define VBLKSIZE        4096
53 #define VBLKMASK        (VBLKSIZE - 1)
54 #define DBPERVBLK       (VBLKSIZE / DEV_BSIZE)
55 #define IPERVBLK        (VBLKSIZE / sizeof(struct dinode))
56 #define INDIRPERVBLK    (VBLKSIZE / sizeof(ufs_daddr_t))
57 #define INO_TO_VBA(fs, x) (fsbtodb(fs, ino_to_fsba(fs, x)) + \
58     (ino_to_fsbo(fs, x) / IPERVBLK) * DBPERVBLK)
59 #define INO_TO_VBO(fs, x) (ino_to_fsbo(fs, x) % IPERVBLK)
60 #define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \
61     ((off) / VBLKSIZE) * DBPERVBLK)
62 #define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
63
64 static char fsbuf[SBSIZE], iobuf[VBLKSIZE];
65 ufs_daddr_t mapbuf[VBLKSIZE / sizeof(ufs_daddr_t)];
66 static int mapblock;
67
68 int poff;
69
70 #ifdef RAWBOOT
71 #define STARTBYTE       8192    /* Where on the media the kernel starts */
72 #endif
73
74 static int block_map(int file_block);
75 static int find(char *path);
76
77 int
78 readit(char *buffer, int count)
79 {
80     int logno, off, size;
81     int cnt2, fsblk, bnum2;
82     struct fs *fs_copy;
83     int n = 0;
84
85     if (poff + count > inode.i_size)
86         count = inode.i_size - poff;
87     while (count > 0 && poff < inode.i_size) {
88         fs_copy = fs;
89         off = blkoff(fs_copy, poff);
90         logno = lblkno(fs_copy, poff);
91         fsblk = block_map(logno);
92         cnt2 = blksize(fs_copy, &inode, logno) - (off & ~VBLKMASK);
93         if (cnt2 > VBLKSIZE)
94                 cnt2 = VBLKSIZE;
95         size = cnt2;
96         bnum2 = FS_TO_VBA(fs_copy, fsblk, off) + boff;
97         off = FS_TO_VBO(fs_copy, fsblk, off);
98         if (    (!off)  && (size <= count)) {
99             devread(buffer, bnum2, cnt2);
100         } else {
101             size -= off;
102             if (size > count)
103                 size = count;
104             devread(iobuf, bnum2, cnt2);
105             bcopy(iobuf+off, buffer, size);
106         }
107         buffer += size;
108         count -= size;
109         poff += size;
110         n += size;
111     }
112     return n;
113 }
114
115 static int
116 find(char *path)
117 {
118     char *rest, ch;
119     int block, blklen, fsboff, off, loc, ino = ROOTINO;
120     struct dirent *dp;
121     char list_only;
122
123     list_only = (path[0] == '?' && path[1] == '\0');
124  loop:
125     devread(iobuf, INO_TO_VBA(fs, ino) + boff, VBLKSIZE);
126     bcopy((void *)&((struct dinode *)iobuf)[INO_TO_VBO(fs, ino)],
127           (void *)&inode.i_din,
128           sizeof (struct dinode));
129     if (!*path)
130         return 1;
131     while (*path == '/')
132         path++;
133     if (!inode.i_size || ((inode.i_mode&IFMT) != IFDIR))
134         return 0;
135     for (rest = path; (ch = *rest) && ch != '/'; rest++) ;
136     *rest = 0;
137     loc = 0;
138     do {
139         if (loc >= inode.i_size) {
140             if (list_only) {
141                 putchar('\n');
142                 return -1;
143             } else {
144                 return 0;
145             }
146         }
147         if (!(off = (loc & VBLKMASK))) {
148             block = lblkno(fs, loc);
149             fsboff = blkoff(fs, loc);
150             blklen = blksize(fs, &inode, block) - fsboff;
151             if (blklen > VBLKSIZE)
152                 blklen = VBLKSIZE;
153             devread(iobuf, FS_TO_VBA(fs, block_map(block), fsboff) + boff,
154                 blklen);
155         }
156         dp = (struct dirent *)(iobuf + off);
157         loc += dp->d_reclen;
158         if (dp->d_fileno && list_only) {
159             puts(dp->d_name);
160             putchar(' ');
161         }
162     } while (!dp->d_fileno || strcmp(path, dp->d_name));
163     ino = dp->d_fileno;
164     *(path = rest) = ch;
165     goto loop;
166 }
167
168
169 static int
170 block_map(int file_block)
171 {
172         int bnum;
173         if (file_block < NDADDR)
174                 return(inode.i_db[file_block]);
175         bnum = FS_TO_VBA(fs, inode.i_ib[0], sizeof(mapbuf[0]) *
176             ((file_block - NDADDR) % NINDIR(fs))) + boff;
177         if (bnum != mapblock) {
178                 devread(mapbuf, bnum, VBLKSIZE);
179                 mapblock = bnum;
180         }
181         return (mapbuf[(file_block - NDADDR) % INDIRPERVBLK]);
182 }
183
184 #ifdef COMPAT_UFS
185
186 #define max(a, b)       ((a) > (b) ? (a) : (b))
187
188 /*
189  * Sanity checks for old file systems.
190  *
191  * XXX - goes away some day.
192  */
193 static void
194 ffs_oldfscompat(fs)
195         struct fs *fs;
196 {
197         int i;
198
199         fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);       /* XXX */
200         fs->fs_interleave = max(fs->fs_interleave, 1);          /* XXX */
201         if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
202                 fs->fs_nrpos = 8;                               /* XXX */
203         if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
204                 quad_t sizepb = fs->fs_bsize;                   /* XXX */
205                                                                 /* XXX */
206                 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
207                 for (i = 0; i < NIADDR; i++) {                  /* XXX */
208                         sizepb *= NINDIR(fs);                   /* XXX */
209                         fs->fs_maxfilesize += sizepb;           /* XXX */
210                 }                                               /* XXX */
211                 fs->fs_qbmask = ~fs->fs_bmask;                  /* XXX */
212                 fs->fs_qfmask = ~fs->fs_fmask;                  /* XXX */
213         }                                                       /* XXX */
214 }
215 #endif
216
217 int
218 openrd(char *name)
219 {
220     int ret;
221     char namecopy[128];
222
223     if (devopen())
224         return 1;
225
226     /*
227      * Load Filesystem info (mount the device).
228      */
229     devread((char *)(fs = (struct fs *)fsbuf), SBLOCK + boff, SBSIZE);
230
231 #ifdef COMPAT_UFS
232     ffs_oldfscompat(fs);
233 #endif
234
235     /*
236      * Find the actual FILE on the mounted device.
237      * Make a copy of the name since find() is destructive.
238      */
239     strcpy(namecopy, name);
240     ret = find(namecopy);
241     if (ret == 0)
242         return 1;
243     if (ret < 0)
244         return -1;
245     poff = 0;
246     return 0;
247 }
248
249 void
250 bcopy(const void *src, void *dst, size_t len) 
251 {
252         const char *s;
253         char *d;
254                  
255         for (d = dst, s = src; len; len--)
256                 *d++ = *s++;
257 }