Fully synchronize sys/boot from FreeBSD-5.x, but add / to the module path
[dragonfly.git] / sys / boot / pc98 / boot2 / 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  * $FreeBSD: src/sys/boot/pc98/boot2/sys.c,v 1.5 2003/09/08 09:11:20 obrien Exp $
28  * $DragonFly: src/sys/boot/pc98/boot2/Attic/sys.c,v 1.3 2003/11/10 06:08:38 dillon Exp $
29  */
30
31 /*
32  * Ported to PC-9801 by Yoshio Kimura
33  */
34
35 #include "boot.h"
36 #include <sys/dirent.h>
37
38 #if 0
39 /* #define BUFSIZE 4096 */
40 #define BUFSIZE MAXBSIZE
41 static char buf[BUFSIZE], fsbuf[SBSIZE], iobuf[MAXBSIZE];
42 #endif
43
44 static char biosdrivedigit;
45
46 #define BUFSIZE 8192
47 #define MAPBUFSIZE BUFSIZE
48 static char buf[BUFSIZE], fsbuf[BUFSIZE], iobuf[BUFSIZE];
49
50 static char mapbuf[MAPBUFSIZE];
51 static int mapblock;
52
53 int poff;
54
55 #ifdef RAWBOOT
56 #define STARTBYTE       8192    /* Where on the media the kernel starts */
57 #endif
58
59 static int block_map(int file_block);
60 static int find(char *path);
61
62 void
63 xread(char *addr, int size)
64 {
65         int count = BUFSIZE;
66         while (size > 0) {
67                 if (BUFSIZE > size)
68                         count = size;
69                 read(buf, count);
70                 pcpy(buf, addr, count);
71                 size -= count;
72                 addr += count;
73         }
74 }
75
76 #ifndef RAWBOOT
77 void
78 read(char *buffer, int count)
79 {
80         int logno, off, size;
81         int cnt2, bnum2;
82         struct fs *fs_copy;
83
84         while (count > 0 && poff < inode.i_size) {
85                 fs_copy = fs;
86                 off = blkoff(fs_copy, poff);
87                 logno = lblkno(fs_copy, poff);
88                 cnt2 = size = blksize(fs_copy, &inode, logno);
89                 bnum2 = fsbtodb(fs_copy, block_map(logno)) + boff;
90                 if (    (!off)  && (size <= count)) {
91                         devread(buffer, bnum2, cnt2);
92                 } else {
93                         size -= off;
94                         if (size > count)
95                                 size = count;
96                         devread(iobuf, bnum2, cnt2);
97                         bcopy(iobuf+off, buffer, size);
98                 }
99                 buffer += size;
100                 count -= size;
101                 poff += size;
102         }
103 }
104 #else
105 void
106 read(char *buffer, int count)
107 {
108         int cnt, bnum, off, size;
109
110         off = STARTBYTE + poff;
111         poff += count;
112
113         /* Read any unaligned bit at the front */
114         cnt = off & 511;
115         if (cnt) {
116                 size = 512-cnt;
117                 if (count < size)
118                         size = count;
119                 devread(iobuf, off >> 9, 512);
120                 bcopy(iobuf+cnt, buffer, size);
121                 count -= size;
122                 off += size;
123                 buffer += size;
124         }
125         size = count & (~511);
126         if (size && (off & (~511))) {
127                 devread(buffer, off >> 9, size);
128                 off += size;
129                 count -= size;
130                 buffer += size;
131         }
132         if (count) {
133                 devread(iobuf, off >> 9, 512);
134                 bcopy(iobuf, buffer, count);
135         }
136 }
137 #endif
138
139 static int
140 find(char *path)
141 {
142         char *rest, ch;
143         int block, off, loc, ino = ROOTINO;
144         struct dirent *dp;
145         char list_only;
146
147         list_only = (path[0] == '?' && path[1] == '\0');
148 loop:
149         devread(iobuf, fsbtodb(fs, ino_to_fsba(fs, ino)) + boff, fs->fs_bsize);
150         bcopy((void *)&((struct dinode *)iobuf)[ino % fs->fs_inopb],
151               (void *)&inode.i_din,
152               sizeof (struct dinode));
153         if (!*path)
154                 return 1;
155         while (*path == '/')
156                 path++;
157         if (!inode.i_size || ((inode.i_mode&IFMT) != IFDIR))
158                 return 0;
159         for (rest = path; (ch = *rest) && ch != '/'; rest++) ;
160         *rest = 0;
161         loc = 0;
162         do {
163                 if (loc >= inode.i_size) {
164                         if (list_only) {
165                                 putchar('\n');
166                                 return -1;
167                         } else {
168                                 return 0;
169                         }
170                 }
171                 if (!(off = blkoff(fs, loc))) {
172                         block = lblkno(fs, loc);
173                         devread(iobuf, fsbtodb(fs, block_map(block)) + boff,
174                                 blksize(fs, &inode, block));
175                 }
176                 dp = (struct dirent *)(iobuf + off);
177                 loc += dp->d_reclen;
178                 if (dp->d_fileno && list_only)
179                         printf("%s ", dp->d_name);
180         } while (!dp->d_fileno || strcmp(path, dp->d_name));
181         ino = dp->d_fileno;
182         *(path = rest) = ch;
183         goto loop;
184 }
185
186
187 static int
188 block_map(int file_block)
189 {
190         int bnum;
191         if (file_block < NDADDR)
192                 return(inode.i_db[file_block]);
193         if ((bnum=fsbtodb(fs, inode.i_ib[0])+boff) != mapblock) {
194                 devread(mapbuf, bnum, fs->fs_bsize);
195                 mapblock = bnum;
196         }
197         return (((int *)mapbuf)[(file_block - NDADDR) % NINDIR(fs)]);
198 }
199
200
201 int
202 openrd(void)
203 {
204         char **devp, *name0 = name, *cp = name0;
205         int biosdrive, dosdev_copy, ret;
206
207         /*******************************************************\
208         * If bracket given look for preceding device name       *
209         \*******************************************************/
210         while (*cp && *cp!='(')
211                 cp++;
212         if (!*cp)
213         {
214                 cp = name0;
215         }
216         else
217         {
218                 /*
219                  * Look for a BIOS drive number (a leading digit followed
220                  * by a colon).
221                  */
222                 biosdrivedigit = '\0';
223                 if (*(name0 + 1) == ':' && *name0 >= '0' && *name0 <= '9') {
224                         biosdrivedigit = *name0;
225                         name0 += 2;
226                 }
227
228                 if (cp++ != name0)
229                 {
230                         for (devp = devs; *devp; devp++)
231                                 if (name0[0] == (*devp)[0] &&
232                                     name0[1] == (*devp)[1])
233                                         break;
234                         if (!*devp)
235                         {
236                                 printf("Unknown device\n");
237                                 return 1;
238                         }
239                         maj = devp-devs;
240                 }
241                 /*******************************************************\
242                 * Look inside brackets for unit number, and partition   *
243                 \*******************************************************/
244                 /*
245                  * Allow any valid digit as the unit number, as the BIOS
246                  * will complain if the unit number is out of range.
247                  * Restricting the range here prevents the possibilty of using
248                  * BIOSes that support more than 2 units.
249                  * XXX Bad values may cause strange errors, need to check if
250                  * what happens when a value out of range is supplied.
251                  */
252                 if (*cp >= '0' && *cp <= '9')
253                         unit = *cp++ - '0';
254                 if (!*cp || (*cp == ',' && !*++cp))
255                         return 1;
256                 if (*cp >= 'a' && *cp <= 'p')
257                         part = *cp++ - 'a';
258                 while (*cp && *cp++!=')') ;
259                 if (!*cp)
260                         return 1;
261         }
262         biosdrive = biosdrivedigit - '0';
263         if (biosdrivedigit == '\0') {
264 #ifdef PC98
265                 biosdrive = dosdev & 0x0f;
266 #else
267                 biosdrive = unit;
268 #endif
269 #if BOOT_HD_BIAS > 0
270                 /* XXX */
271                 if (maj == 4)
272                         biosdrive += BOOT_HD_BIAS;
273 #endif
274         }
275         switch(maj)
276         {
277 #ifdef PC98
278         case 4: /* da */
279                 dosdev_copy = biosdrive | 0xA0; /* SCSI HD or MO */
280 #else   /* IBM-PC */
281         case 0:
282         case 4:
283                 dosdev_copy = biosdrive | 0x80;
284 #endif
285                 break;
286 #ifdef PC98
287         case 0: /* wd */
288         case 2: /* 1200KB fd */
289                 dosdev_copy = (maj << 3) | unit | 0x80;
290 #else
291         case 2:
292                 dosdev_copy = biosdrive;
293 #endif
294                 break;
295 #ifdef PC98
296         case 6: /* 1440KB fd */
297                 dosdev_copy = (maj << 3) | unit;
298                 break;
299 #endif
300         default:
301                 printf("Unknown device\n");
302                 return 1;
303         }
304         dosdev = dosdev_copy;
305 #if 0
306         /* XXX this is useful, but misplaced. */
307         printf("dosdev= %x, biosdrive = %d, unit = %d, maj = %d\n",
308                 dosdev_copy, biosdrive, unit, maj);
309 #endif
310
311         /***********************************************\
312         * Now we know the disk unit and part,           *
313         * Load disk info, (open the device)             *
314         \***********************************************/
315         if (devopen())
316                 return 1;
317
318 #ifndef RAWBOOT
319         /***********************************************\
320         * Load Filesystem info (mount the device)       *
321         \***********************************************/
322         devread((char *)(fs = (struct fs *)fsbuf), SBLOCK + boff, SBSIZE);
323         /***********************************************\
324         * Find the actual FILE on the mounted device    *
325         \***********************************************/
326         ret = find(cp);
327         name = cp;
328         if (ret == 0)
329                 return 1;
330         if (ret < 0) {
331                 name = NULL;
332                 return -1;
333         }
334         poff = 0;
335 #endif /* RAWBOOT */
336         return 0;
337 }