main.c revision 150751
113044Sasami/*- 213044Sasami * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 313044Sasami * All rights reserved. 413044Sasami * 513044Sasami * Redistribution and use in source and binary forms, with or without 613044Sasami * modification, are permitted provided that the following conditions 713044Sasami * are met: 813044Sasami * 1. Redistributions of source code must retain the above copyright 913044Sasami * notice, this list of conditions and the following disclaimer. 1013044Sasami * 2. Redistributions in binary form must reproduce the above copyright 1113044Sasami * notice, this list of conditions and the following disclaimer in the 1213044Sasami * documentation and/or other materials provided with the distribution. 1313044Sasami * 1413044Sasami * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1513044Sasami * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1613044Sasami * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1713044Sasami * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1813044Sasami * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1913044Sasami * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2013044Sasami * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2113044Sasami * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2213044Sasami * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2313044Sasami * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2413044Sasami * SUCH DAMAGE. 2513044Sasami */ 2613044Sasami 2713044Sasami#include <sys/cdefs.h> 2813044Sasami__FBSDID("$FreeBSD: head/sys/boot/pc98/loader/main.c 150751 2005-09-30 13:24:14Z nyan $"); 2913044Sasami 3013044Sasami/* 3113044Sasami * MD bootstrap main() and assorted miscellaneous 3213044Sasami * commands. 3313044Sasami */ 3413044Sasami 3536628Scharnier#include <stand.h> 3636628Scharnier#include <string.h> 3750476Speter#include <machine/bootinfo.h> 3836628Scharnier#include <sys/reboot.h> 3936628Scharnier 4013044Sasami#include "bootstrap.h" 4148568Sbillf#include "libi386/libi386.h" 4213044Sasami#include "btxv86.h" 4313044Sasami 4445329Speter#define KARGS_FLAGS_CD 0x1 4513044Sasami#define KARGS_FLAGS_PXE 0x2 4613044Sasami 4713044Sasami/* Arguments passed in from the boot1/boot2 loader */ 4813044Sasamistatic struct 4913044Sasami{ 5013044Sasami u_int32_t howto; 5169793Sobrien u_int32_t bootdev; 5213044Sasami u_int32_t bootflags; 5313044Sasami u_int32_t pxeinfo; 5413044Sasami u_int32_t res2; 5513044Sasami u_int32_t bootinfo; 5613044Sasami} *kargs; 5739228Sgibbs 5813052Sasamistatic u_int32_t initial_howto; 5913044Sasamistatic u_int32_t initial_bootdev; 6013044Sasamistatic struct bootinfo *initial_bootinfo; 6113044Sasami 6213044Sasamistruct arch_switch archsw; /* MI/MD interface boundary */ 6313044Sasami 6413044Sasamistatic void extract_currdev(void); 6513044Sasamistatic int isa_inb(int port); 6613044Sasamistatic void isa_outb(int port, int value); 6713044Sasamivoid exit(int code); 6813044Sasami 6913044Sasami/* from vers.c */ 7013044Sasamiextern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; 7113044Sasami 7213044Sasami/* XXX debugging */ 7313044Sasamiextern char end[]; 7413044Sasami 7513762Sasamiint 7613762Sasamimain(void) 7713044Sasami{ 7813044Sasami int i; 7913044Sasami 8013044Sasami /* Pick up arguments */ 8113044Sasami kargs = (void *)__args; 8213044Sasami initial_howto = kargs->howto; 8313044Sasami initial_bootdev = kargs->bootdev; 8413044Sasami initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL; 8513044Sasami 8613044Sasami /* 8713044Sasami * Initialise the heap as early as possible. Once this is done, malloc() is usable. 8813044Sasami */ 8913044Sasami bios_getmem(); 9013044Sasami 9113044Sasami setheap((void *)end, (void *)bios_basemem); 9213044Sasami 9313044Sasami /* 9413044Sasami * XXX Chicken-and-egg problem; we want to have console output early, but some 9513044Sasami * console attributes may depend on reading from eg. the boot device, which we 9613044Sasami * can't do yet. 9713044Sasami * 9813044Sasami * We can use printf() etc. once this is done. 9913044Sasami * If the previous boot stage has requested a serial console, prefer that. 10013044Sasami */ 10113044Sasami bi_setboothowto(initial_howto); 10213044Sasami if (initial_howto & RB_MULTIPLE) { 10313044Sasami if (initial_howto & RB_SERIAL) 10413044Sasami setenv("console", "comconsole vidconsole", 1); 10513044Sasami else 10613044Sasami setenv("console", "vidconsole comconsole", 1); 10713044Sasami } else if (initial_howto & RB_SERIAL) 10813044Sasami setenv("console", "comconsole", 1); 10913044Sasami else if (initial_howto & RB_MUTE) 11013044Sasami setenv("console", "nullconsole", 1); 11113044Sasami cons_probe(); 11213044Sasami 11313044Sasami /* 11413044Sasami * Initialise the block cache 11513044Sasami */ 11613044Sasami bcache_init(32, 512); /* 16k cache XXX tune this */ 11713044Sasami 11813044Sasami /* 11913044Sasami * Special handling for PXE and CD booting. 12013044Sasami */ 12113044Sasami if (kargs->bootinfo == 0) { 12213044Sasami /* 12313044Sasami * We only want the PXE disk to try to init itself in the below 12413044Sasami * walk through devsw if we actually booted off of PXE. 12513044Sasami */ 12613044Sasami if (kargs->bootflags & KARGS_FLAGS_PXE) 12713044Sasami pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL); 12813044Sasami else if (kargs->bootflags & KARGS_FLAGS_CD) 12913044Sasami bc_add(initial_bootdev); 13013044Sasami } 13113044Sasami 13213044Sasami /* 13313044Sasami * March through the device switch probing for things. 13413044Sasami */ 13513044Sasami for (i = 0; devsw[i] != NULL; i++) 13613044Sasami if (devsw[i]->dv_init != NULL) 13713044Sasami (devsw[i]->dv_init)(); 13813044Sasami printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024); 13913044Sasami if (initial_bootinfo != NULL) { 14013044Sasami initial_bootinfo->bi_basemem = bios_basemem / 1024; 14113044Sasami initial_bootinfo->bi_extmem = bios_extmem / 1024; 14213044Sasami } 14313044Sasami 14413044Sasami printf("\n"); 14513044Sasami printf("%s, Revision %s\n", bootprog_name, bootprog_rev); 14613044Sasami printf("(%s, %s)\n", bootprog_maker, bootprog_date); 14713044Sasami 14813044Sasami extract_currdev(); /* set $currdev and $loaddev */ 14913044Sasami setenv("LINES", "24", 1); /* optional */ 15013044Sasami 15113044Sasami archsw.arch_autoload = i386_autoload; 15213044Sasami archsw.arch_getdev = i386_getdev; 15313044Sasami archsw.arch_copyin = i386_copyin; 15413044Sasami archsw.arch_copyout = i386_copyout; 15513044Sasami archsw.arch_readin = i386_readin; 15613044Sasami archsw.arch_isainb = isa_inb; 15713044Sasami archsw.arch_isaoutb = isa_outb; 15813044Sasami 15913044Sasami interact(); /* doesn't return */ 16013044Sasami 16113044Sasami /* if we ever get here, it is an error */ 16213044Sasami return (1); 16313044Sasami} 16413044Sasami 16532116Simp/* 16632116Simp * Set the 'current device' by (if possible) recovering the boot device as 16732116Simp * supplied by the initial bootstrap. 16832116Simp * 16932116Simp * XXX should be extended for netbooting. 17032116Simp */ 17132116Simpstatic void 17232116Simpextract_currdev(void) 17332116Simp{ 17445329Speter struct i386_devdesc new_currdev; 17545329Speter int major, biosdev = -1; 17645329Speter 17745329Speter /* Assume we are booting from a BIOS disk by default */ 17845329Speter new_currdev.d_dev = &biosdisk; 17945329Speter 18013044Sasami /* new-style boot loaders such as pxeldr and cdldr */ 18113044Sasami if (kargs->bootinfo == 0) { 18213044Sasami if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) { 18313044Sasami /* we are booting from a CD with cdboot */ 18413044Sasami new_currdev.d_dev = &bioscd; 18513044Sasami new_currdev.d_kind.bioscd.unit = bc_bios2unit(initial_bootdev); 18613044Sasami } else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) { 18713044Sasami /* we are booting from pxeldr */ 18813044Sasami new_currdev.d_dev = &pxedisk; 18913044Sasami new_currdev.d_kind.netif.unit = 0; 19013044Sasami } else { 19113044Sasami /* we don't know what our boot device is */ 19213044Sasami new_currdev.d_kind.biosdisk.slice = -1; 19313044Sasami new_currdev.d_kind.biosdisk.partition = 0; 19413044Sasami biosdev = -1; 19513044Sasami } 19636628Scharnier } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) { 19713044Sasami /* The passed-in boot device is bad */ 19813044Sasami new_currdev.d_kind.biosdisk.slice = -1; 19913044Sasami new_currdev.d_kind.biosdisk.partition = 0; 20013044Sasami biosdev = -1; 20113044Sasami } else { 20213044Sasami new_currdev.d_kind.biosdisk.slice = (B_ADAPTOR(initial_bootdev) << 4) + 20313044Sasami B_CONTROLLER(initial_bootdev) - 1; 20413044Sasami new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev); 20513044Sasami biosdev = initial_bootinfo->bi_bios_dev; 20613044Sasami major = B_TYPE(initial_bootdev); 20751690Sbillf 20813044Sasami /* 20913044Sasami * If we are booted by an old bootstrap, we have to guess at the BIOS 21013044Sasami * unit number. We will loose if there is more than one disk type 21113044Sasami * and we are not booting from the lowest-numbered disk type 21213044Sasami * (ie. SCSI when IDE also exists). 21313044Sasami */ 21413044Sasami if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) { /* biosdev doesn't match major */ 21513044Sasami if (B_TYPE(initial_bootdev) == 6) 21613044Sasami biosdev = 0x30 + B_UNIT(initial_bootdev); 21713044Sasami else 21813044Sasami biosdev = (major << 3) + 0x80 + B_UNIT(initial_bootdev); 21913044Sasami } 22013044Sasami } 22113044Sasami new_currdev.d_type = new_currdev.d_dev->dv_type; 22213044Sasami 22313044Sasami /* 22413044Sasami * If we are booting off of a BIOS disk and we didn't succeed in determining 22513044Sasami * which one we booted off of, just use disk0: as a reasonable default. 22613044Sasami */ 22713044Sasami if ((new_currdev.d_type == biosdisk.dv_type) && 22813044Sasami ((new_currdev.d_kind.biosdisk.unit = bd_bios2unit(biosdev)) == -1)) { 22913044Sasami printf("Can't work out which disk we are booting from.\n" 23013044Sasami "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev); 23113044Sasami new_currdev.d_kind.biosdisk.unit = 0; 23248568Sbillf } 23313044Sasami env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev), 23413044Sasami i386_setcurrdev, env_nounset); 23513044Sasami env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset, 23613044Sasami env_nounset); 23713044Sasami} 23813044Sasami 23913044SasamiCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); 24013044Sasami 24113044Sasamistatic int 24213044Sasamicommand_reboot(int argc, char *argv[]) 24348568Sbillf{ 24413044Sasami int i; 24513044Sasami 24613044Sasami for (i = 0; devsw[i] != NULL; ++i) 24713044Sasami if (devsw[i]->dv_cleanup != NULL) 24813044Sasami (devsw[i]->dv_cleanup)(); 24913044Sasami 25013044Sasami printf("Rebooting...\n"); 25113044Sasami delay(1000000); 25213044Sasami __exit(0); 25313044Sasami} 25413044Sasami 25513044Sasami/* provide this for panic, as it's not in the startup code */ 25613044Sasamivoid 25713044Sasamiexit(int code) 25813044Sasami{ 25913044Sasami __exit(code); 26013044Sasami} 26113044Sasami 26213044SasamiCOMMAND_SET(heap, "heap", "show heap usage", command_heap); 26313044Sasami 26413044Sasamistatic int 26513044Sasamicommand_heap(int argc, char *argv[]) 26613044Sasami{ 26713044Sasami mallocstats(); 26813044Sasami printf("heap base at %p, top at %p\n", end, sbrk(0)); 26913044Sasami return(CMD_OK); 27013044Sasami} 27113044Sasami 27213044Sasami/* ISA bus access functions for PnP, derived from <machine/cpufunc.h> */ 27313044Sasamistatic int 27413044Sasamiisa_inb(int port) 27513044Sasami{ 27613044Sasami u_char data; 27713044Sasami 27813044Sasami if (__builtin_constant_p(port) && 27913044Sasami (((port) & 0xffff) < 0x100) && 28013044Sasami ((port) < 0x10000)) { 28113044Sasami __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port))); 28213044Sasami } else { 28313044Sasami __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); 28413044Sasami } 28513044Sasami return(data); 28613044Sasami} 28713044Sasami 28813044Sasamistatic void 28913044Sasamiisa_outb(int port, int value) 29013044Sasami{ 29113044Sasami u_char al = value; 29213044Sasami 29313044Sasami if (__builtin_constant_p(port) && 29413044Sasami (((port) & 0xffff) < 0x100) && 29513044Sasami ((port) < 0x10000)) { 29613044Sasami __asm __volatile("outb %0,%1" : : "a" (al), "id" ((u_short)(port))); 29713044Sasami } else { 29813044Sasami __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); 29913044Sasami } 30013044Sasami} 30113044Sasami 30213044Sasami