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