143561Skato/*- 243561Skato * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 343561Skato * All rights reserved. 443561Skato * 543561Skato * Redistribution and use in source and binary forms, with or without 643561Skato * modification, are permitted provided that the following conditions 743561Skato * are met: 843561Skato * 1. Redistributions of source code must retain the above copyright 943561Skato * notice, this list of conditions and the following disclaimer. 1043561Skato * 2. Redistributions in binary form must reproduce the above copyright 1143561Skato * notice, this list of conditions and the following disclaimer in the 1243561Skato * documentation and/or other materials provided with the distribution. 1343561Skato * 1443561Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1543561Skato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1643561Skato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1743561Skato * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1843561Skato * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1943561Skato * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2043561Skato * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2143561Skato * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2243561Skato * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2343561Skato * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2443561Skato * SUCH DAMAGE. 2543561Skato */ 2643561Skato 27119880Sobrien#include <sys/cdefs.h> 28119880Sobrien__FBSDID("$FreeBSD: stable/11/stand/pc98/loader/main.c 344290 2019-02-19 18:48:17Z kevans $"); 29119880Sobrien 3043561Skato/* 3143561Skato * MD bootstrap main() and assorted miscellaneous 3243561Skato * commands. 3343561Skato */ 3443561Skato 3543561Skato#include <stand.h> 36235264Savg#include <stddef.h> 3743561Skato#include <string.h> 3843561Skato#include <machine/bootinfo.h> 39240854Snyan#include <machine/cpufunc.h> 40220311Smarcel#include <sys/param.h> 4143561Skato#include <sys/reboot.h> 4243561Skato 4343561Skato#include "bootstrap.h" 44235264Savg#include "common/bootargs.h" 4545241Skato#include "libi386/libi386.h" 46201339Snyan#include "libpc98/libpc98.h" 4743561Skato#include "btxv86.h" 4843561Skato 49235264SavgCTASSERT(sizeof(struct bootargs) == BOOTARGS_SIZE); 50235264SavgCTASSERT(offsetof(struct bootargs, bootinfo) == BA_BOOTINFO); 51235264SavgCTASSERT(offsetof(struct bootargs, bootflags) == BA_BOOTFLAGS); 52235264SavgCTASSERT(offsetof(struct bootinfo, bi_size) == BI_SIZE); 5358871Skato 5443561Skato/* Arguments passed in from the boot1/boot2 loader */ 55235264Savgstatic struct bootargs *kargs; 5643561Skato 5743561Skatostatic u_int32_t initial_howto; 5843561Skatostatic u_int32_t initial_bootdev; 5943561Skatostatic struct bootinfo *initial_bootinfo; 6043561Skato 6143561Skatostruct arch_switch archsw; /* MI/MD interface boundary */ 6243561Skato 6343561Skatostatic void extract_currdev(void); 6443561Skatostatic int isa_inb(int port); 6543561Skatostatic void isa_outb(int port, int value); 6668358Snyanvoid exit(int code); 6743561Skato 6843561Skato/* XXX debugging */ 6943561Skatoextern char end[]; 7043561Skato 71153600Snyanstatic void *heap_top; 72153600Snyanstatic void *heap_bottom; 73153600Snyan 74220311Smarcelstatic uint64_t 75220311Smarcelpc98_loadaddr(u_int type, void *data, uint64_t addr) 76220311Smarcel{ 77220311Smarcel struct stat st; 78220311Smarcel 79220311Smarcel if (type == LOAD_ELF) 80220311Smarcel return (roundup(addr, PAGE_SIZE)); 81220311Smarcel 82220311Smarcel /* We cannot use 15M-16M area on pc98. */ 83220311Smarcel if (type == LOAD_RAW && addr < 0x1000000 && stat(data, &st) == 0 && 84220311Smarcel (st.st_size == -1 || addr + st.st_size > 0xf00000)) 85220311Smarcel addr = 0x1000000; 86220311Smarcel return (addr); 87220311Smarcel} 88220311Smarcel 8968358Snyanint 9043561Skatomain(void) 9143561Skato{ 9243561Skato int i; 9343561Skato 94201339Snyan /* Set machine type to PC98_SYSTEM_PARAMETER. */ 95201339Snyan set_machine_type(); 96201339Snyan 9743561Skato /* Pick up arguments */ 9843561Skato kargs = (void *)__args; 9943561Skato initial_howto = kargs->howto; 10043561Skato initial_bootdev = kargs->bootdev; 10158871Skato initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL; 10243561Skato 103181436Sjhb /* Initialize the v86 register set to a known-good state. */ 104181436Sjhb bzero(&v86, sizeof(v86)); 105181436Sjhb v86.efl = PSL_RESERVED_DEFAULT | PSL_I; 106181436Sjhb 10743561Skato /* 10843561Skato * Initialise the heap as early as possible. Once this is done, malloc() is usable. 10943561Skato */ 11055342Snyan bios_getmem(); 11159167Skato 112200253Snyan#if defined(LOADER_BZIP2_SUPPORT) 113200255Snyan if (high_heap_size > 0) { 114200255Snyan heap_top = PTOV(high_heap_base + high_heap_size); 115200255Snyan heap_bottom = PTOV(high_heap_base); 116200255Snyan if (high_heap_base < memtop_copyin) 117200255Snyan memtop_copyin = high_heap_base; 118200255Snyan } else 119153600Snyan#endif 120200255Snyan { 121200255Snyan heap_top = (void *)PTOV(bios_basemem); 122200255Snyan heap_bottom = (void *)end; 123200255Snyan } 124153600Snyan setheap(heap_bottom, heap_top); 12558871Skato 12643561Skato /* 12743561Skato * XXX Chicken-and-egg problem; we want to have console output early, but some 12843561Skato * console attributes may depend on reading from eg. the boot device, which we 12943561Skato * can't do yet. 13043561Skato * 13143561Skato * We can use printf() etc. once this is done. 13243561Skato * If the previous boot stage has requested a serial console, prefer that. 13343561Skato */ 134150751Snyan bi_setboothowto(initial_howto); 135146698Sjhb if (initial_howto & RB_MULTIPLE) { 136146698Sjhb if (initial_howto & RB_SERIAL) 137146698Sjhb setenv("console", "comconsole vidconsole", 1); 138146698Sjhb else 139146698Sjhb setenv("console", "vidconsole comconsole", 1); 140146698Sjhb } else if (initial_howto & RB_SERIAL) 14143561Skato setenv("console", "comconsole", 1); 142146698Sjhb else if (initial_howto & RB_MUTE) 14366246Skato setenv("console", "nullconsole", 1); 14443561Skato cons_probe(); 14543561Skato 14643561Skato /* 147298230Sallanjude * Initialise the block cache. Set the upper limit. 14843561Skato */ 149298230Sallanjude bcache_init(32768, 512); 15043561Skato 15143561Skato /* 15286131Snyan * Special handling for PXE and CD booting. 15358871Skato */ 154126970Snyan if (kargs->bootinfo == 0) { 15586131Snyan /* 15686131Snyan * We only want the PXE disk to try to init itself in the below 15786131Snyan * walk through devsw if we actually booted off of PXE. 15886131Snyan */ 15986131Snyan if (kargs->bootflags & KARGS_FLAGS_PXE) 16086131Snyan pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL); 16186131Snyan else if (kargs->bootflags & KARGS_FLAGS_CD) 16286131Snyan bc_add(initial_bootdev); 16358871Skato } 16458871Skato 165190046Snyan archsw.arch_autoload = i386_autoload; 166190046Snyan archsw.arch_getdev = i386_getdev; 167190046Snyan archsw.arch_copyin = i386_copyin; 168190046Snyan archsw.arch_copyout = i386_copyout; 169190046Snyan archsw.arch_readin = i386_readin; 170190046Snyan archsw.arch_isainb = isa_inb; 171190046Snyan archsw.arch_isaoutb = isa_outb; 172220311Smarcel archsw.arch_loadaddr = pc98_loadaddr; 173190046Snyan 17458871Skato /* 17543561Skato * March through the device switch probing for things. 17643561Skato */ 17743561Skato for (i = 0; devsw[i] != NULL; i++) 17843561Skato if (devsw[i]->dv_init != NULL) 17943561Skato (devsw[i]->dv_init)(); 18055342Snyan printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024); 181136891Snyan if (initial_bootinfo != NULL) { 182136891Snyan initial_bootinfo->bi_basemem = bios_basemem / 1024; 183136891Snyan initial_bootinfo->bi_extmem = bios_extmem / 1024; 184136891Snyan } 18543561Skato 186312318Semaste printf("\n%s", bootprog_info); 18743561Skato 18843561Skato extract_currdev(); /* set $currdev and $loaddev */ 18943561Skato setenv("LINES", "24", 1); /* optional */ 19043561Skato 191330311Skevans interact(); /* doesn't return */ 19268358Snyan 19368358Snyan /* if we ever get here, it is an error */ 19468358Snyan return (1); 19543561Skato} 19643561Skato 19743561Skato/* 19843561Skato * Set the 'current device' by (if possible) recovering the boot device as 19943561Skato * supplied by the initial bootstrap. 20043561Skato * 20143561Skato * XXX should be extended for netbooting. 20243561Skato */ 20343561Skatostatic void 20443561Skatoextract_currdev(void) 20543561Skato{ 206240852Snyan struct i386_devdesc new_currdev; 207240852Snyan int major; 208240852Snyan int biosdev = -1; 20943561Skato 21058871Skato /* Assume we are booting from a BIOS disk by default */ 211332154Skevans new_currdev.dd.d_dev = &biosdisk; 21243561Skato 21358871Skato /* new-style boot loaders such as pxeldr and cdldr */ 214126970Snyan if (kargs->bootinfo == 0) { 21558871Skato if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) { 21686131Snyan /* we are booting from a CD with cdboot */ 217332154Skevans new_currdev.dd.d_dev = &bioscd; 218332154Skevans new_currdev.dd.d_unit = bc_bios2unit(initial_bootdev); 21958871Skato } else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) { 22058871Skato /* we are booting from pxeldr */ 221332154Skevans new_currdev.dd.d_dev = &pxedisk; 222332154Skevans new_currdev.dd.d_unit = 0; 22358871Skato } else { 22458871Skato /* we don't know what our boot device is */ 22568358Snyan new_currdev.d_kind.biosdisk.slice = -1; 22668358Snyan new_currdev.d_kind.biosdisk.partition = 0; 22758871Skato biosdev = -1; 22858871Skato } 22958871Skato } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) { 23043561Skato /* The passed-in boot device is bad */ 23168358Snyan new_currdev.d_kind.biosdisk.slice = -1; 23268358Snyan new_currdev.d_kind.biosdisk.partition = 0; 23343561Skato biosdev = -1; 23443561Skato } else { 235172924Snyan new_currdev.d_kind.biosdisk.slice = B_SLICE(initial_bootdev) - 1; 23668358Snyan new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev); 23743561Skato biosdev = initial_bootinfo->bi_bios_dev; 23843561Skato major = B_TYPE(initial_bootdev); 23943561Skato 24043561Skato /* 24143561Skato * If we are booted by an old bootstrap, we have to guess at the BIOS 242160964Syar * unit number. We will lose if there is more than one disk type 24343561Skato * and we are not booting from the lowest-numbered disk type 24443561Skato * (ie. SCSI when IDE also exists). 24543561Skato */ 24653218Snyan if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) { /* biosdev doesn't match major */ 24744463Skato if (B_TYPE(initial_bootdev) == 6) 24844463Skato biosdev = 0x30 + B_UNIT(initial_bootdev); 24944463Skato else 25044463Skato biosdev = (major << 3) + 0x80 + B_UNIT(initial_bootdev); 25153218Snyan } 25243561Skato } 253240852Snyan 25458871Skato /* 25558871Skato * If we are booting off of a BIOS disk and we didn't succeed in determining 25658871Skato * which one we booted off of, just use disk0: as a reasonable default. 25758871Skato */ 258339405Simp if ((new_currdev.dd.d_dev->dv_type == biosdisk.dv_type) && 259332154Skevans ((new_currdev.dd.d_unit = bd_bios2unit(biosdev)) == -1)) { 26043561Skato printf("Can't work out which disk we are booting from.\n" 26143561Skato "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev); 262332154Skevans new_currdev.dd.d_unit = 0; 26343561Skato } 264240852Snyan 26568358Snyan env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev), 26668358Snyan i386_setcurrdev, env_nounset); 26768358Snyan env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset, 26868358Snyan env_nounset); 26943561Skato} 27043561Skato 27143561SkatoCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); 27243561Skato 27343561Skatostatic int 27443561Skatocommand_reboot(int argc, char *argv[]) 27543561Skato{ 27659535Snyan int i; 27743561Skato 27859535Snyan for (i = 0; devsw[i] != NULL; ++i) 27959535Snyan if (devsw[i]->dv_cleanup != NULL) 28059535Snyan (devsw[i]->dv_cleanup)(); 28159535Snyan 28243561Skato printf("Rebooting...\n"); 28343561Skato delay(1000000); 28443561Skato __exit(0); 28543561Skato} 28643561Skato 28743561Skato/* provide this for panic, as it's not in the startup code */ 28843561Skatovoid 28943561Skatoexit(int code) 29043561Skato{ 29143561Skato __exit(code); 29243561Skato} 29343561Skato 29443561SkatoCOMMAND_SET(heap, "heap", "show heap usage", command_heap); 29543561Skato 29643561Skatostatic int 29743561Skatocommand_heap(int argc, char *argv[]) 29843561Skato{ 29943561Skato mallocstats(); 300153600Snyan printf("heap base at %p, top at %p, upper limit at %p\n", heap_bottom, 301153600Snyan sbrk(0), heap_top); 30243561Skato return(CMD_OK); 30343561Skato} 30443561Skato 305240854Snyan/* ISA bus access functions for PnP. */ 306240852Snyanstatic int 30743561Skatoisa_inb(int port) 30843561Skato{ 309240854Snyan 310240854Snyan return (inb(port)); 31143561Skato} 31243561Skato 31343561Skatostatic void 31443561Skatoisa_outb(int port, int value) 31543561Skato{ 316240854Snyan 317240854Snyan outb(port, value); 31843561Skato} 319