Initial import from FreeBSD RELENG_4:
[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  */
30
31 #include <string.h>
32 #include <sys/param.h>
33 #include <sys/time.h>
34
35 #include <ufs/ffs/fs.h>
36 #include <ufs/ufs/quota.h>
37 #include <ufs/ufs/inode.h>
38
39 #include <sys/dirent.h>
40
41 #define COMPAT_UFS
42
43 struct fs *fs;
44 struct inode inode;
45 int boff = 0;
46
47 /*
48  * We use 4k `virtual' blocks for filesystem data, whatever the actual
49  * filesystem block size. FFS blocks are always a multiple of 4k.
50  */
51 #define VBLKSIZE        4096
52 #define VBLKMASK        (VBLKSIZE - 1)
53 #define DBPERVBLK       (VBLKSIZE / DEV_BSIZE)
54 #define IPERVBLK        (VBLKSIZE / sizeof(struct dinode))
55 #define INDIRPERVBLK    (VBLKSIZE / sizeof(ufs_daddr_t))
56 #define INO_TO_VBA(fs, x) (fsbtodb(fs, ino_to_fsba(fs, x)) + \
57     (ino_to_fsbo(fs, x) / IPERVBLK) * DBPERVBLK)
58 #define INO_TO_VBO(fs, x) (ino_to_fsbo(fs, x) % IPERVBLK)
59 #define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \
60     ((off) / VBLKSIZE) * DBPERVBLK)
61 #define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK)
62
63 static char fsbuf[SBSIZE], iobuf[VBLKSIZE];
64 ufs_daddr_t mapbuf[VBLKSIZE / sizeof(ufs_daddr_t)];
65 static int mapblock;
66
67 int poff;
68
69 #ifdef RAWBOOT
70 #define STARTBYTE       8192    /* Where on the media the kernel starts */
71 #endif
72
73 static int block_map(int file_block);
74 static int find(char *path);
75
76 int
77 readit(char *buffer, int count)
78 {
79     int logno, off, size;
80     int cnt2, fsblk, bnum2;
81     struct fs *fs_copy;
82     int n = 0;
83
84     if (poff + count > inode.i_size)
85         count = inode.i_size - poff;
86     while (count > 0 && poff < inode.i_size) {
87         fs_copy = fs;
88         off = blkoff(fs_copy, poff);
89         logno = lblkno(fs_copy, poff);
90         fsblk = block_map(logno);
91         cnt2 = blksize(fs_copy, &inode, logno) - (off & ~VBLKMASK);
92         if (cnt2 > VBLKSIZE)
93                 cnt2 = VBLKSIZE;
94         size = cnt2;
95         bnum2 = FS_TO_VBA(fs_copy, fsblk, off) + boff;
96         off = FS_TO_VBO(fs_copy, fsblk, off);
97         if (    (!off)  && (size <= count)) {
98             devread(buffer, bnum2, cnt2);
99         } else {
100             size -= off;
101             if (size > count)
102                 size = count;
103             devread(iobuf, bnum2, cnt2);
104             bcopy(iobuf+off, buffer, size);
105         }
106         buffer += size;
107         count -= size;
108         poff += size;
109         n += size;
110     }
111     return n;
112 }
113
114 static int
115 find(char *path)
116 {
117     char *rest, ch;
118     int block, blklen, fsboff, off, loc, ino = ROOTINO;
119     struct dirent *dp;
120     char list_only;
121
122     list_only = (path[0] == '?' && path[1] == '\0');
123  loop:
124     devread(iobuf, INO_TO_VBA(fs, ino) + boff, VBLKSIZE);
125     bcopy((void *)&((struct dinode *)iobuf)[INO_TO_VBO(fs, ino)],
126           (void *)&inode.i_din,
127           sizeof (struct dinode));
128     if (!*path)
129         return 1;
130     while (*path == '/')
131         path++;
132     if (!inode.i_size || ((inode.i_mode&IFMT) != IFDIR))
133         return 0;
134     for (rest = path; (ch = *rest) && ch != '/'; rest++) ;
135     *rest = 0;
136     loc = 0;
137     do {
138         if (loc >= inode.i_size) {
139             if (list_only) {
140                 putchar('\n');
141                 return -1;
142             } else {
143                 return 0;
144             }
145         }
146         if (!(off = (loc & VBLKMASK))) {
147             block = lblkno(fs, loc);
148             fsboff = blkoff(fs, loc);
149             blklen = blksize(fs, &inode, block) - fsboff;
150             if (blklen > VBLKSIZE)
151                 blklen = VBLKSIZE;
152             devread(iobuf, FS_TO_VBA(fs, block_map(block), fsboff) + boff,
153                 blklen);
154         }
155         dp = (struct dirent *)(iobuf + off);
156         loc += dp->d_reclen;
157         if (dp->d_fileno && list_only) {
158             puts(dp->d_name);
159             putchar(' ');
160         }
161     } while (!dp->d_fileno || strcmp(path, dp->d_name));
162     ino = dp->d_fileno;
163     *(path = rest) = ch;
164     goto loop;
165 }
166
167
168 static int
169 block_map(int file_block)
170 {
171         int bnum;
172         if (file_block < NDADDR)
173                 return(inode.i_db[file_block]);
174         bnum = FS_TO_VBA(fs, inode.i_ib[0], sizeof(mapbuf[0]) *
175             ((file_block - NDADDR) % NINDIR(fs))) + boff;
176         if (bnum != mapblock) {
177                 devread(mapbuf, bnum, VBLKSIZE);
178                 mapblock = bnum;
179         }
180         return (mapbuf[(file_block - NDADDR) % INDIRPERVBLK]);
181 }
182
183 #ifdef COMPAT_UFS
184
185 #define max(a, b)       ((a) > (b) ? (a) : (b))
186
187 /*
188  * Sanity checks for old file systems.
189  *
190  * XXX - goes away some day.
191  */
192 static void
193 ffs_oldfscompat(fs)
194         struct fs *fs;
195 {
196         int i;
197
198         fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);       /* XXX */
199         fs->fs_interleave = max(fs->fs_interleave, 1);          /* XXX */
200         if (fs->fs_postblformat == FS_42POSTBLFMT)              /* XXX */
201                 fs->fs_nrpos = 8;                               /* XXX */
202         if (fs->fs_inodefmt < FS_44INODEFMT) {                  /* XXX */
203                 quad_t sizepb = fs->fs_bsize;                   /* XXX */
204                                                                 /* XXX */
205                 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
206                 for (i = 0; i < NIADDR; i++) {                  /* XXX */
207                         sizepb *= NINDIR(fs);                   /* XXX */
208                         fs->fs_maxfilesize += sizepb;           /* XXX */
209                 }                                               /* XXX */
210                 fs->fs_qbmask = ~fs->fs_bmask;                  /* XXX */
211                 fs->fs_qfmask = ~fs->fs_fmask;                  /* XXX */
212         }                                                       /* XXX */
213 }
214 #endif
215
216 int
217 openrd(char *name)
218 {
219     int ret;
220     char namecopy[128];
221
222     if (devopen())
223         return 1;
224
225     /*
226      * Load Filesystem info (mount the device).
227      */
228     devread((char *)(fs = (struct fs *)fsbuf), SBLOCK + boff, SBSIZE);
229
230 #ifdef COMPAT_UFS
231     ffs_oldfscompat(fs);
232 #endif
233
234     /*
235      * Find the actual FILE on the mounted device.
236      * Make a copy of the name since find() is destructive.
237      */
238     strcpy(namecopy, name);
239     ret = find(namecopy);
240     if (ret == 0)
241         return 1;
242     if (ret < 0)
243         return -1;
244     poff = 0;
245     return 0;
246 }
247
248 void
249 bcopy(const void *src, void *dst, size_t len) 
250 {
251         const char *s;
252         char *d;
253                  
254         for (d = dst, s = src; len; len--)
255                 *d++ = *s++;
256 }