summaryrefslogtreecommitdiffstats
path: root/sys/boot/pc98/boot2/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/pc98/boot2/sys.c')
-rw-r--r--sys/boot/pc98/boot2/sys.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/sys/boot/pc98/boot2/sys.c b/sys/boot/pc98/boot2/sys.c
new file mode 100644
index 0000000..c0617ca
--- /dev/null
+++ b/sys/boot/pc98/boot2/sys.c
@@ -0,0 +1,338 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:36:34 rpd
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Ported to PC-9801 by Yoshio Kimura
+ */
+
+#include "boot.h"
+#include <sys/dirent.h>
+
+#if 0
+/* #define BUFSIZE 4096 */
+#define BUFSIZE MAXBSIZE
+static char buf[BUFSIZE], fsbuf[SBSIZE], iobuf[MAXBSIZE];
+#endif
+
+static char biosdrivedigit;
+
+#define BUFSIZE 8192
+#define MAPBUFSIZE BUFSIZE
+static char buf[BUFSIZE], fsbuf[BUFSIZE], iobuf[BUFSIZE];
+
+static char mapbuf[MAPBUFSIZE];
+static int mapblock;
+
+int poff;
+
+#ifdef RAWBOOT
+#define STARTBYTE 8192 /* Where on the media the kernel starts */
+#endif
+
+static int block_map(int file_block);
+static int find(char *path);
+
+void
+xread(char *addr, int size)
+{
+ int count = BUFSIZE;
+ while (size > 0) {
+ if (BUFSIZE > size)
+ count = size;
+ read(buf, count);
+ pcpy(buf, addr, count);
+ size -= count;
+ addr += count;
+ }
+}
+
+#ifndef RAWBOOT
+void
+read(char *buffer, int count)
+{
+ int logno, off, size;
+ int cnt2, bnum2;
+ struct fs *fs_copy;
+
+ while (count > 0 && poff < inode.i_size) {
+ fs_copy = fs;
+ off = blkoff(fs_copy, poff);
+ logno = lblkno(fs_copy, poff);
+ cnt2 = size = blksize(fs_copy, &inode, logno);
+ bnum2 = fsbtodb(fs_copy, block_map(logno)) + boff;
+ if ( (!off) && (size <= count)) {
+ devread(buffer, bnum2, cnt2);
+ } else {
+ size -= off;
+ if (size > count)
+ size = count;
+ devread(iobuf, bnum2, cnt2);
+ bcopy(iobuf+off, buffer, size);
+ }
+ buffer += size;
+ count -= size;
+ poff += size;
+ }
+}
+#else
+void
+read(char *buffer, int count)
+{
+ int cnt, bnum, off, size;
+
+ off = STARTBYTE + poff;
+ poff += count;
+
+ /* Read any unaligned bit at the front */
+ cnt = off & 511;
+ if (cnt) {
+ size = 512-cnt;
+ if (count < size)
+ size = count;
+ devread(iobuf, off >> 9, 512);
+ bcopy(iobuf+cnt, buffer, size);
+ count -= size;
+ off += size;
+ buffer += size;
+ }
+ size = count & (~511);
+ if (size && (off & (~511))) {
+ devread(buffer, off >> 9, size);
+ off += size;
+ count -= size;
+ buffer += size;
+ }
+ if (count) {
+ devread(iobuf, off >> 9, 512);
+ bcopy(iobuf, buffer, count);
+ }
+}
+#endif
+
+static int
+find(char *path)
+{
+ char *rest, ch;
+ int block, off, loc, ino = ROOTINO;
+ struct dirent *dp;
+ char list_only;
+
+ list_only = (path[0] == '?' && path[1] == '\0');
+loop:
+ devread(iobuf, fsbtodb(fs, ino_to_fsba(fs, ino)) + boff, fs->fs_bsize);
+ bcopy((void *)&((struct dinode *)iobuf)[ino % fs->fs_inopb],
+ (void *)&inode.i_din,
+ sizeof (struct dinode));
+ if (!*path)
+ return 1;
+ while (*path == '/')
+ path++;
+ if (!inode.i_size || ((inode.i_mode&IFMT) != IFDIR))
+ return 0;
+ for (rest = path; (ch = *rest) && ch != '/'; rest++) ;
+ *rest = 0;
+ loc = 0;
+ do {
+ if (loc >= inode.i_size) {
+ if (list_only) {
+ putchar('\n');
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+ if (!(off = blkoff(fs, loc))) {
+ block = lblkno(fs, loc);
+ devread(iobuf, fsbtodb(fs, block_map(block)) + boff,
+ blksize(fs, &inode, block));
+ }
+ dp = (struct dirent *)(iobuf + off);
+ loc += dp->d_reclen;
+ if (dp->d_fileno && list_only)
+ printf("%s ", dp->d_name);
+ } while (!dp->d_fileno || strcmp(path, dp->d_name));
+ ino = dp->d_fileno;
+ *(path = rest) = ch;
+ goto loop;
+}
+
+
+static int
+block_map(int file_block)
+{
+ int bnum;
+ if (file_block < NDADDR)
+ return(inode.i_db[file_block]);
+ if ((bnum=fsbtodb(fs, inode.i_ib[0])+boff) != mapblock) {
+ devread(mapbuf, bnum, fs->fs_bsize);
+ mapblock = bnum;
+ }
+ return (((int *)mapbuf)[(file_block - NDADDR) % NINDIR(fs)]);
+}
+
+
+int
+openrd(void)
+{
+ char **devp, *name0 = name, *cp = name0;
+ int biosdrive, dosdev_copy, ret;
+
+ /*******************************************************\
+ * If bracket given look for preceding device name *
+ \*******************************************************/
+ while (*cp && *cp!='(')
+ cp++;
+ if (!*cp)
+ {
+ cp = name0;
+ }
+ else
+ {
+ /*
+ * Look for a BIOS drive number (a leading digit followed
+ * by a colon).
+ */
+ biosdrivedigit = '\0';
+ if (*(name0 + 1) == ':' && *name0 >= '0' && *name0 <= '9') {
+ biosdrivedigit = *name0;
+ name0 += 2;
+ }
+
+ if (cp++ != name0)
+ {
+ for (devp = devs; *devp; devp++)
+ if (name0[0] == (*devp)[0] &&
+ name0[1] == (*devp)[1])
+ break;
+ if (!*devp)
+ {
+ printf("Unknown device\n");
+ return 1;
+ }
+ maj = devp-devs;
+ }
+ /*******************************************************\
+ * Look inside brackets for unit number, and partition *
+ \*******************************************************/
+ /*
+ * Allow any valid digit as the unit number, as the BIOS
+ * will complain if the unit number is out of range.
+ * Restricting the range here prevents the possibilty of using
+ * BIOSes that support more than 2 units.
+ * XXX Bad values may cause strange errors, need to check if
+ * what happens when a value out of range is supplied.
+ */
+ if (*cp >= '0' && *cp <= '9')
+ unit = *cp++ - '0';
+ if (!*cp || (*cp == ',' && !*++cp))
+ return 1;
+ if (*cp >= 'a' && *cp <= 'p')
+ part = *cp++ - 'a';
+ while (*cp && *cp++!=')') ;
+ if (!*cp)
+ return 1;
+ }
+ biosdrive = biosdrivedigit - '0';
+ if (biosdrivedigit == '\0') {
+#ifdef PC98
+ biosdrive = dosdev & 0x0f;
+#else
+ biosdrive = unit;
+#endif
+#if BOOT_HD_BIAS > 0
+ /* XXX */
+ if (maj == 4)
+ biosdrive += BOOT_HD_BIAS;
+#endif
+ }
+ switch(maj)
+ {
+#ifdef PC98
+ case 4: /* da */
+ dosdev_copy = biosdrive | 0xA0; /* SCSI HD or MO */
+#else /* IBM-PC */
+ case 0:
+ case 4:
+ dosdev_copy = biosdrive | 0x80;
+#endif
+ break;
+#ifdef PC98
+ case 0: /* wd */
+ case 2: /* 1200KB fd */
+ dosdev_copy = (maj << 3) | unit | 0x80;
+#else
+ case 2:
+ dosdev_copy = biosdrive;
+#endif
+ break;
+#ifdef PC98
+ case 6: /* 1440KB fd */
+ dosdev_copy = (maj << 3) | unit;
+ break;
+#endif
+ default:
+ printf("Unknown device\n");
+ return 1;
+ }
+ dosdev = dosdev_copy;
+#if 0
+ /* XXX this is useful, but misplaced. */
+ printf("dosdev= %x, biosdrive = %d, unit = %d, maj = %d\n",
+ dosdev_copy, biosdrive, unit, maj);
+#endif
+
+ /***********************************************\
+ * Now we know the disk unit and part, *
+ * Load disk info, (open the device) *
+ \***********************************************/
+ if (devopen())
+ return 1;
+
+#ifndef RAWBOOT
+ /***********************************************\
+ * Load Filesystem info (mount the device) *
+ \***********************************************/
+ devread((char *)(fs = (struct fs *)fsbuf), SBLOCK + boff, SBSIZE);
+ /***********************************************\
+ * Find the actual FILE on the mounted device *
+ \***********************************************/
+ ret = find(cp);
+ name = cp;
+ if (ret == 0)
+ return 1;
+ if (ret < 0) {
+ name = NULL;
+ return -1;
+ }
+ poff = 0;
+#endif /* RAWBOOT */
+ return 0;
+}
OpenPOWER on IntegriCloud