Fully synchronize sys/boot from FreeBSD-5.x, but add / to the module path
[dragonfly.git] / sys / boot / pc98 / boot2 / sys.c
CommitLineData
984263bc
MD
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
5ee58eed
MD
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 $
984263bc
MD
29 */
30
31/*
32 * Ported to PC-9801 by Yoshio Kimura
33 */
34
35#include "boot.h"
36#include <sys/dirent.h>
984263bc
MD
37
38#if 0
39/* #define BUFSIZE 4096 */
40#define BUFSIZE MAXBSIZE
41static char buf[BUFSIZE], fsbuf[SBSIZE], iobuf[MAXBSIZE];
42#endif
43
44static char biosdrivedigit;
45
46#define BUFSIZE 8192
47#define MAPBUFSIZE BUFSIZE
48static char buf[BUFSIZE], fsbuf[BUFSIZE], iobuf[BUFSIZE];
49
50static char mapbuf[MAPBUFSIZE];
51static int mapblock;
52
53int poff;
54
55#ifdef RAWBOOT
56#define STARTBYTE 8192 /* Where on the media the kernel starts */
57#endif
58
59static int block_map(int file_block);
60static int find(char *path);
61
62void
63xread(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
77void
78read(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
105void
106read(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
139static int
140find(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');
148loop:
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
187static int
188block_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
201int
202openrd(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}