summaryrefslogtreecommitdiffstats
path: root/sys/pc98/boot/biosboot/boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pc98/boot/biosboot/boot.c')
-rw-r--r--sys/pc98/boot/biosboot/boot.c397
1 files changed, 397 insertions, 0 deletions
diff --git a/sys/pc98/boot/biosboot/boot.c b/sys/pc98/boot/biosboot/boot.c
new file mode 100644
index 0000000..284f036
--- /dev/null
+++ b/sys/pc98/boot/biosboot/boot.c
@@ -0,0 +1,397 @@
+/*
+ * 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, [92/04/03 16:51:14 rvb]
+ * $Id: boot.c,v 1.50 1996/05/11 04:27:24 bde Exp $
+ */
+
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <sys/param.h>
+#include "boot.h"
+#include <a.out.h>
+#include <sys/reboot.h>
+#include <machine/bootinfo.h>
+
+#define ouraddr (BOOTSEG << 4) /* XXX */
+
+#define NAMEBUF_LEN (8*1024)
+
+char namebuf[NAMEBUF_LEN];
+struct exec head;
+struct bootinfo bootinfo;
+int loadflags;
+
+static void getbootdev(char *ptr, int *howto);
+static void loadprog(void);
+
+/* NORETURN */
+void
+boot(int drive)
+{
+ int ret;
+
+#ifdef PROBE_KEYBOARD
+ if (probe_keyboard()) {
+ init_serial();
+ loadflags |= RB_SERIAL;
+ printf("\nNo keyboard found.");
+ }
+#endif
+
+#ifdef FORCE_COMCONSOLE
+ init_serial();
+ loadflags |= RB_SERIAL;
+ printf("\nSerial console forced.");
+#endif
+
+ /* Pick up the story from the Bios on geometry of disks */
+
+#ifdef PC98
+ for(ret = 0; ret < 2; ret ++) {
+ if (*(unsigned char*)0x1155d & (1 << ret)) {
+ bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
+ }
+#else /* IBM-PC */
+ for(ret = 0; ret < N_BIOS_GEOM; ret ++)
+ bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
+#endif /* PC98 */
+ }
+
+ bootinfo.bi_basemem = memsize(0);
+ bootinfo.bi_extmem = memsize(1);
+ bootinfo.bi_memsizes_valid = 1;
+
+ gateA20();
+
+#ifdef PC98
+ /* set machine type to PC98_SYSTEM_PARAMETER */
+ machine_check();
+#endif /* PC98 */
+
+ /*
+ * The default boot device is the first partition in the
+ * compatibility slice on the boot drive.
+ */
+ dosdev = drive;
+#ifdef PC98
+ maj = (drive&0x70) >> 3; /* a good first bet */
+ unit = drive & 0x0f;
+#else /* IBM-PC */
+ maj = 2;
+ unit = drive & 0x7f;
+#ifdef dontneed
+ slice = 0;
+ part = 0;
+#endif
+ if (drive & 0x80) {
+ /* Hard drive. Adjust. */
+ maj = 0;
+#if BOOT_HD_BIAS > 0
+ if (unit >= BOOT_HD_BIAS) {
+ /*
+ * The drive is probably a SCSI drive with a unit
+ * number BOOT_HD_BIAS less than the BIOS drive
+ * number.
+ */
+ maj = 4;
+ unit -= BOOT_HD_BIAS;
+ }
+#endif
+ }
+#endif /* PC98 */
+
+loadstart:
+ /* print this all each time.. (saves space to do so) */
+ /* If we have looped, use the previous entries as defaults */
+ printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\n"
+ "Usage: [[[%d:][%s](%d,a)]%s][-abcCdhrsv]\n"
+ "Use 1:sd(0,a)kernel to boot sd0 if it is BIOS drive 1\n"
+ "Use ? for file list or press Enter for defaults\n\nBoot: ",
+ ouraddr, bootinfo.bi_basemem, bootinfo.bi_extmem,
+#ifdef PC98
+ dosdev & 0x0f, devs[maj], unit, name);
+#else
+ dosdev & 0x7f, devs[maj], unit, name);
+#endif
+
+ name = dflname; /* re-initialize in case of loop */
+ loadflags &= RB_SERIAL; /* clear all, but leave serial console */
+ getbootdev(namebuf, &loadflags);
+ ret = openrd();
+ if (ret != 0) {
+ if (ret > 0)
+ printf("Can't find %s\n", name);
+ goto loadstart;
+ }
+/* if (inode.i_mode&IEXEC)
+ loadflags |= RB_KDB;
+*/
+ loadprog();
+ goto loadstart;
+}
+
+static void
+loadprog(void)
+{
+ long int startaddr;
+ long int addr; /* physical address.. not directly useable */
+ long int bootdev;
+ int i;
+ unsigned pad;
+
+ read((void *)&head, sizeof(head));
+ if ( N_BADMAG(head)) {
+ printf("Invalid format!\n");
+ return;
+ }
+
+ poff = N_TXTOFF(head);
+ /*if(poff==0)
+ poff = 32;*/
+
+ /*
+ * We assume that the entry address is the same as the lowest text
+ * address and that the kernel startup code handles relocation by
+ * this address rounded down to a multiple of 16M.
+ */
+ startaddr = head.a_entry & 0x00FFFFFF;
+ addr = startaddr;
+ printf("Booting %d:%s(%d,%c)%s @ 0x%x\n"
+#ifdef PC98
+ , dosdev & 0x0f
+#else
+ , dosdev & 0x7f
+#endif
+ , devs[maj]
+ , unit
+ , 'a'+part
+ , name
+ , addr);
+ if(addr < 0x00100000)
+ {
+ /*
+ * Bail out, instead of risking to damage the BIOS
+ * variables, the loader, or the adapter memory area.
+ * We don't support loading below 1 MB any more.
+ */
+ printf("Start address too low\n");
+ return;
+ }
+ printf("text=0x%x ", head.a_text);
+ /********************************************************/
+ /* LOAD THE TEXT SEGMENT */
+ /********************************************************/
+ xread((void *)addr, head.a_text);
+ addr += head.a_text;
+
+ /********************************************************/
+ /* Load the Initialised data after the text */
+ /********************************************************/
+ while (addr & PAGE_MASK)
+ *(char *)addr++ = 0;
+
+ printf("data=0x%x ", head.a_data);
+ xread((void *)addr, head.a_data);
+ addr += head.a_data;
+
+ /********************************************************/
+ /* Skip over the uninitialised data */
+ /* (but clear it) */
+ /********************************************************/
+ printf("bss=0x%x ", head.a_bss);
+
+/*
+ * XXX however, we should be checking that we don't load ... into
+ * nonexistent memory. A full symbol table is unlikely to fit on 4MB
+ * machines.
+ */
+ pbzero((void *)addr,head.a_bss);
+ addr += head.a_bss;
+
+ /* Pad to a page boundary. */
+ pad = (unsigned)addr & PAGE_MASK;
+ if (pad != 0) {
+ pad = PAGE_SIZE - pad;
+ addr += pad;
+ }
+ bootinfo.bi_symtab = addr;
+
+ /********************************************************/
+ /* Copy the symbol table size */
+ /********************************************************/
+ pcpy(&head.a_syms, (void *)addr, sizeof(head.a_syms));
+ addr += sizeof(head.a_syms);
+
+ /********************************************************/
+ /* Load the symbol table */
+ /********************************************************/
+ printf("symbols=[+0x%x+0x%x+0x%x", pad, sizeof(head.a_syms),
+ head.a_syms);
+ xread((void *)addr, head.a_syms);
+ addr += head.a_syms;
+
+ /********************************************************/
+ /* Load the string table size */
+ /********************************************************/
+ read((void *)&i, sizeof(int));
+ pcpy(&i, (void *)addr, sizeof(int));
+ i -= sizeof(int);
+ addr += sizeof(int);
+
+ /********************************************************/
+ /* Load the string table */
+ /********************************************************/
+ printf("+0x%x+0x%x]\n", sizeof(int), i);
+ xread((void *)addr, i);
+ addr += i;
+
+ bootinfo.bi_esymtab = addr;
+
+#ifdef notyet
+#ifdef PC98
+ /*
+ * MO boot support by KATO Takenori (Nov 27, 1995)
+ *
+ * Major device number should be cahnged into 20 (od) from
+ * 4 (sd) when you boot from MO.
+ */
+ if (maj == 4) {
+ /* SCSI device*/
+ if (((*(unsigned char*)0x11482) & (1 << unit)) == 0) {
+ /*
+ * XXX
+ * Boot device is not HDD
+ */
+ int scsi_id;
+ unit = 0;
+ /*
+ * XXX
+ * If you want to boot from MO, its ID should be below
+ * than that of other SCSI devices except for HDD becaus
+ * they seem to be a MO in following code.
+ */
+ for (scsi_id = 0; scsi_id < unit; scsi_id++)
+ if ((*(unsigned char*)0x11482) & (1 << scsi_id) == 0)
+ unit++;
+ }
+ maj = 20; /* od */
+ }
+#endif
+#endif
+
+ /*
+ * For backwards compatibility, use the previously-unused adaptor
+ * and controller bitfields to hold the slice number.
+ */
+ bootdev = MAKEBOOTDEV(maj, (slice >> 4), slice & 0xf, unit, part);
+
+ bootinfo.bi_version = BOOTINFO_VERSION;
+ bootinfo.bi_kernelname = name + ouraddr;
+ bootinfo.bi_nfs_diskless = NULL;
+ bootinfo.bi_size = sizeof(bootinfo);
+ printf("total=0x%x entry point=0x%x\n", (int)addr, (int)startaddr);
+ startprog((int)startaddr, loadflags | RB_BOOTINFO, bootdev,
+ (int)&bootinfo + ouraddr);
+}
+
+void
+getbootdev(char *ptr, int *howto)
+{
+ char c;
+
+ /*
+ * Be paranoid and make doubly sure that the input buffer is empty.
+ */
+ if (*howto & RB_SERIAL)
+ init_serial();
+
+ if (!gets(ptr)) {
+ putchar('\n');
+ return;
+ }
+ while ((c = *ptr) != '\0') {
+nextarg:
+ while (c == ' ')
+ c = *++ptr;
+ if (c == '-')
+ while ((c = *++ptr) != '\0') {
+ if (c == ' ')
+ goto nextarg;
+ if (c == 'C')
+ *howto |= RB_CDROM;
+ if (c == 'a')
+ *howto |= RB_ASKNAME;
+ if (c == 'b')
+ *howto |= RB_HALT;
+ if (c == 'c')
+ *howto |= RB_CONFIG;
+ if (c == 'd')
+ *howto |= RB_KDB;
+ if (c == 'h') {
+ *howto ^= RB_SERIAL;
+ if (*howto & RB_SERIAL)
+ init_serial();
+ }
+ if (c == 'r')
+ *howto |= RB_DFLTROOT;
+ if (c == 's')
+ *howto |= RB_SINGLE;
+ if (c == 'v')
+ *howto |= RB_VERBOSE;
+ }
+ if (c == '\0')
+ return;
+ name = ptr;
+ while (*++ptr != '\0') {
+ if (*ptr == ' ') {
+ *ptr++ = '\0';
+ break;
+ }
+ }
+ }
+}
OpenPOWER on IntegriCloud