main.c revision 181436
1251881Speter/*- 2251881Speter * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3251881Speter * All rights reserved. 4251881Speter * 5251881Speter * Redistribution and use in source and binary forms, with or without 6251881Speter * modification, are permitted provided that the following conditions 7251881Speter * are met: 8251881Speter * 1. Redistributions of source code must retain the above copyright 9251881Speter * notice, this list of conditions and the following disclaimer. 10251881Speter * 2. Redistributions in binary form must reproduce the above copyright 11251881Speter * notice, this list of conditions and the following disclaimer in the 12251881Speter * documentation and/or other materials provided with the distribution. 13251881Speter * 14251881Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15251881Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16251881Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17251881Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18251881Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22251881Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23251881Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24251881Speter * SUCH DAMAGE. 25251881Speter */ 26251881Speter 27251881Speter#include <sys/cdefs.h> 28251881Speter__FBSDID("$FreeBSD: head/sys/boot/pc98/loader/main.c 181436 2008-08-08 19:41:20Z jhb $"); 29251881Speter 30251881Speter/* 31251881Speter * MD bootstrap main() and assorted miscellaneous 32251881Speter * commands. 33251881Speter */ 34251881Speter 35251881Speter#include <stand.h> 36251881Speter#include <string.h> 37251881Speter#include <machine/bootinfo.h> 38251881Speter#include <machine/psl.h> 39251881Speter#include <sys/reboot.h> 40251881Speter 41251881Speter#include "bootstrap.h" 42251881Speter#include "libi386/libi386.h" 43251881Speter#include "btxv86.h" 44251881Speter 45251881Speter#define KARGS_FLAGS_CD 0x1 46251881Speter#define KARGS_FLAGS_PXE 0x2 47251881Speter 48251881Speter/* Arguments passed in from the boot1/boot2 loader */ 49251881Speterstatic struct 50251881Speter{ 51251881Speter u_int32_t howto; 52251881Speter u_int32_t bootdev; 53251881Speter u_int32_t bootflags; 54251881Speter u_int32_t pxeinfo; 55251881Speter u_int32_t res2; 56251881Speter u_int32_t bootinfo; 57251881Speter} *kargs; 58251881Speter 59251881Speterstatic u_int32_t initial_howto; 60251881Speterstatic u_int32_t initial_bootdev; 61251881Speterstatic struct bootinfo *initial_bootinfo; 62251881Speter 63251881Speterstruct arch_switch archsw; /* MI/MD interface boundary */ 64251881Speter 65251881Speterstatic void extract_currdev(void); 66251881Speterstatic int isa_inb(int port); 67251881Speterstatic void isa_outb(int port, int value); 68251881Spetervoid exit(int code); 69251881Speter 70251881Speter/* from vers.c */ 71251881Speterextern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; 72251881Speter 73251881Speter/* XXX debugging */ 74251881Speterextern char end[]; 75251881Speter 76251881Speterstatic void *heap_top; 77251881Speterstatic void *heap_bottom; 78251881Speter 79251881Speterint 80251881Spetermain(void) 81251881Speter{ 82251881Speter int i; 83251881Speter 84251881Speter /* Pick up arguments */ 85251881Speter kargs = (void *)__args; 86251881Speter initial_howto = kargs->howto; 87251881Speter initial_bootdev = kargs->bootdev; 88251881Speter initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL; 89251881Speter 90251881Speter /* Initialize the v86 register set to a known-good state. */ 91251881Speter bzero(&v86, sizeof(v86)); 92251881Speter v86.efl = PSL_RESERVED_DEFAULT | PSL_I; 93251881Speter 94251881Speter /* 95251881Speter * Initialise the heap as early as possible. Once this is done, malloc() is usable. 96251881Speter */ 97251881Speter bios_getmem(); 98251881Speter 99251881Speter#ifdef LOADER_BZIP2_SUPPORT 100251881Speter heap_top = PTOV(memtop_copyin); 101251881Speter memtop_copyin -= 0x300000; 102251881Speter heap_bottom = PTOV(memtop_copyin); 103251881Speter#else 104251881Speter heap_top = (void *)bios_basemem; 105251881Speter heap_bottom = (void *)end; 106251881Speter#endif 107251881Speter setheap(heap_bottom, heap_top); 108251881Speter 109251881Speter /* 110251881Speter * XXX Chicken-and-egg problem; we want to have console output early, but some 111251881Speter * console attributes may depend on reading from eg. the boot device, which we 112251881Speter * can't do yet. 113251881Speter * 114251881Speter * We can use printf() etc. once this is done. 115251881Speter * If the previous boot stage has requested a serial console, prefer that. 116251881Speter */ 117251881Speter bi_setboothowto(initial_howto); 118251881Speter if (initial_howto & RB_MULTIPLE) { 119251881Speter if (initial_howto & RB_SERIAL) 120251881Speter setenv("console", "comconsole vidconsole", 1); 121251881Speter else 122251881Speter setenv("console", "vidconsole comconsole", 1); 123251881Speter } else if (initial_howto & RB_SERIAL) 124251881Speter setenv("console", "comconsole", 1); 125251881Speter else if (initial_howto & RB_MUTE) 126251881Speter setenv("console", "nullconsole", 1); 127251881Speter cons_probe(); 128251881Speter 129251881Speter /* 130251881Speter * Initialise the block cache 131251881Speter */ 132251881Speter bcache_init(32, 512); /* 16k cache XXX tune this */ 133251881Speter 134251881Speter /* 135251881Speter * Special handling for PXE and CD booting. 136251881Speter */ 137251881Speter if (kargs->bootinfo == 0) { 138251881Speter /* 139251881Speter * We only want the PXE disk to try to init itself in the below 140251881Speter * walk through devsw if we actually booted off of PXE. 141251881Speter */ 142251881Speter if (kargs->bootflags & KARGS_FLAGS_PXE) 143251881Speter pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL); 144251881Speter else if (kargs->bootflags & KARGS_FLAGS_CD) 145251881Speter bc_add(initial_bootdev); 146251881Speter } 147251881Speter 148251881Speter /* 149251881Speter * March through the device switch probing for things. 150251881Speter */ 151251881Speter for (i = 0; devsw[i] != NULL; i++) 152251881Speter if (devsw[i]->dv_init != NULL) 153251881Speter (devsw[i]->dv_init)(); 154251881Speter printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024); 155251881Speter if (initial_bootinfo != NULL) { 156251881Speter initial_bootinfo->bi_basemem = bios_basemem / 1024; 157251881Speter initial_bootinfo->bi_extmem = bios_extmem / 1024; 158251881Speter } 159251881Speter 160251881Speter printf("\n"); 161251881Speter printf("%s, Revision %s\n", bootprog_name, bootprog_rev); 162251881Speter printf("(%s, %s)\n", bootprog_maker, bootprog_date); 163251881Speter 164251881Speter extract_currdev(); /* set $currdev and $loaddev */ 165251881Speter setenv("LINES", "24", 1); /* optional */ 166251881Speter 167251881Speter archsw.arch_autoload = i386_autoload; 168251881Speter archsw.arch_getdev = i386_getdev; 169251881Speter archsw.arch_copyin = i386_copyin; 170251881Speter archsw.arch_copyout = i386_copyout; 171251881Speter archsw.arch_readin = i386_readin; 172251881Speter archsw.arch_isainb = isa_inb; 173251881Speter archsw.arch_isaoutb = isa_outb; 174251881Speter 175251881Speter interact(); /* doesn't return */ 176251881Speter 177251881Speter /* if we ever get here, it is an error */ 178251881Speter return (1); 179251881Speter} 180251881Speter 181251881Speter/* 182251881Speter * Set the 'current device' by (if possible) recovering the boot device as 183251881Speter * supplied by the initial bootstrap. 184251881Speter * 185251881Speter * XXX should be extended for netbooting. 186251881Speter */ 187251881Speterstatic void 188251881Speterextract_currdev(void) 189251881Speter{ 190251881Speter struct i386_devdesc new_currdev; 191251881Speter int major, biosdev = -1; 192251881Speter 193251881Speter /* Assume we are booting from a BIOS disk by default */ 194251881Speter new_currdev.d_dev = &biosdisk; 195251881Speter 196251881Speter /* new-style boot loaders such as pxeldr and cdldr */ 197251881Speter if (kargs->bootinfo == 0) { 198251881Speter if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) { 199251881Speter /* we are booting from a CD with cdboot */ 200251881Speter new_currdev.d_dev = &bioscd; 201251881Speter new_currdev.d_unit = bc_bios2unit(initial_bootdev); 202251881Speter } else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) { 203251881Speter /* we are booting from pxeldr */ 204251881Speter new_currdev.d_dev = &pxedisk; 205251881Speter new_currdev.d_unit = 0; 206251881Speter } else { 207251881Speter /* we don't know what our boot device is */ 208251881Speter new_currdev.d_kind.biosdisk.slice = -1; 209251881Speter new_currdev.d_kind.biosdisk.partition = 0; 210251881Speter biosdev = -1; 211251881Speter } 212251881Speter } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) { 213251881Speter /* The passed-in boot device is bad */ 214251881Speter new_currdev.d_kind.biosdisk.slice = -1; 215251881Speter new_currdev.d_kind.biosdisk.partition = 0; 216251881Speter biosdev = -1; 217251881Speter } else { 218251881Speter new_currdev.d_kind.biosdisk.slice = B_SLICE(initial_bootdev) - 1; 219251881Speter new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev); 220251881Speter biosdev = initial_bootinfo->bi_bios_dev; 221251881Speter major = B_TYPE(initial_bootdev); 222251881Speter 223251881Speter /* 224251881Speter * If we are booted by an old bootstrap, we have to guess at the BIOS 225251881Speter * unit number. We will lose if there is more than one disk type 226251881Speter * and we are not booting from the lowest-numbered disk type 227251881Speter * (ie. SCSI when IDE also exists). 228251881Speter */ 229251881Speter if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) { /* biosdev doesn't match major */ 230251881Speter if (B_TYPE(initial_bootdev) == 6) 231251881Speter biosdev = 0x30 + B_UNIT(initial_bootdev); 232251881Speter else 233251881Speter biosdev = (major << 3) + 0x80 + B_UNIT(initial_bootdev); 234251881Speter } 235251881Speter } 236251881Speter new_currdev.d_type = new_currdev.d_dev->dv_type; 237251881Speter 238251881Speter /* 239251881Speter * If we are booting off of a BIOS disk and we didn't succeed in determining 240251881Speter * which one we booted off of, just use disk0: as a reasonable default. 241251881Speter */ 242251881Speter if ((new_currdev.d_type == biosdisk.dv_type) && 243251881Speter ((new_currdev.d_unit = bd_bios2unit(biosdev)) == -1)) { 244251881Speter printf("Can't work out which disk we are booting from.\n" 245251881Speter "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev); 246251881Speter new_currdev.d_unit = 0; 247251881Speter } 248251881Speter env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev), 249251881Speter i386_setcurrdev, env_nounset); 250251881Speter env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset, 251251881Speter env_nounset); 252251881Speter} 253251881Speter 254251881SpeterCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); 255251881Speter 256251881Speterstatic int 257251881Spetercommand_reboot(int argc, char *argv[]) 258251881Speter{ 259251881Speter int i; 260251881Speter 261251881Speter for (i = 0; devsw[i] != NULL; ++i) 262251881Speter if (devsw[i]->dv_cleanup != NULL) 263251881Speter (devsw[i]->dv_cleanup)(); 264251881Speter 265251881Speter printf("Rebooting...\n"); 266251881Speter delay(1000000); 267251881Speter __exit(0); 268251881Speter} 269251881Speter 270251881Speter/* provide this for panic, as it's not in the startup code */ 271251881Spetervoid 272251881Speterexit(int code) 273251881Speter{ 274251881Speter __exit(code); 275251881Speter} 276251881Speter 277251881SpeterCOMMAND_SET(heap, "heap", "show heap usage", command_heap); 278251881Speter 279251881Speterstatic int 280251881Spetercommand_heap(int argc, char *argv[]) 281251881Speter{ 282251881Speter mallocstats(); 283251881Speter printf("heap base at %p, top at %p, upper limit at %p\n", heap_bottom, 284251881Speter sbrk(0), heap_top); 285251881Speter return(CMD_OK); 286251881Speter} 287251881Speter 288251881Speter/* ISA bus access functions for PnP, derived from <machine/cpufunc.h> */ 289251881Speterstatic int 290251881Speterisa_inb(int port) 291251881Speter{ 292251881Speter u_char data; 293251881Speter 294251881Speter if (__builtin_constant_p(port) && 295251881Speter (((port) & 0xffff) < 0x100) && 296251881Speter ((port) < 0x10000)) { 297251881Speter __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port))); 298251881Speter } else { 299251881Speter __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); 300251881Speter } 301251881Speter return(data); 302251881Speter} 303251881Speter 304251881Speterstatic void 305251881Speterisa_outb(int port, int value) 306251881Speter{ 307251881Speter u_char al = value; 308251881Speter 309251881Speter if (__builtin_constant_p(port) && 310251881Speter (((port) & 0xffff) < 0x100) && 311251881Speter ((port) < 0x10000)) { 312251881Speter __asm __volatile("outb %0,%1" : : "a" (al), "id" ((u_short)(port))); 313251881Speter } else { 314251881Speter __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); 315251881Speter } 316251881Speter} 317251881Speter 318251881Speter