Index: head/sys/boot/i386/libi386/biosmem.c =================================================================== --- head/sys/boot/i386/libi386/biosmem.c (revision 153588) +++ head/sys/boot/i386/libi386/biosmem.c (revision 153589) @@ -1,107 +1,107 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Obtain memory configuration information from the BIOS */ #include #include "libi386.h" #include "btxv86.h" -vm_offset_t memtop; +vm_offset_t memtop, memtop_copyin; u_int32_t bios_basemem, bios_extmem; #define SMAPSIG 0x534D4150 struct smap { u_int64_t base; u_int64_t length; u_int32_t type; } __packed; static struct smap smap; void bios_getmem(void) { /* Parse system memory map */ v86.ebx = 0; do { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe820*/ v86.eax = 0xe820; v86.ecx = sizeof(struct smap); v86.edx = SMAPSIG; v86.es = VTOPSEG(&smap); v86.edi = VTOPOFF(&smap); v86int(); if ((v86.efl & 1) || (v86.eax != SMAPSIG)) break; /* look for a low-memory segment that's large enough */ if ((smap.type == 1) && (smap.base == 0) && (smap.length >= (512 * 1024))) bios_basemem = smap.length; /* look for the first segment in 'extended' memory */ if ((smap.type == 1) && (smap.base == 0x100000)) { bios_extmem = smap.length; } } while (v86.ebx != 0); /* Fall back to the old compatibility function for base memory */ if (bios_basemem == 0) { v86.ctl = 0; v86.addr = 0x12; /* int 0x12 */ v86int(); bios_basemem = (v86.eax & 0xffff) * 1024; } /* Fall back through several compatibility functions for extended memory */ if (bios_extmem == 0) { v86.ctl = V86_FLAGS; v86.addr = 0x15; /* int 0x15 function 0xe801*/ v86.eax = 0xe801; v86int(); if (!(v86.efl & 1)) { bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024; } } if (bios_extmem == 0) { v86.ctl = 0; v86.addr = 0x15; /* int 0x15 function 0x88*/ v86.eax = 0x8800; v86int(); bios_extmem = (v86.eax & 0xffff) * 1024; } /* Set memtop to actual top of memory */ - memtop = 0x100000 + bios_extmem; + memtop = memtop_copyin = 0x100000 + bios_extmem; } Index: head/sys/boot/i386/libi386/i386_copy.c =================================================================== --- head/sys/boot/i386/libi386/i386_copy.c (revision 153588) +++ head/sys/boot/i386/libi386/i386_copy.c (revision 153589) @@ -1,75 +1,75 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * MD primitives supporting placement of module data * * XXX should check load address/size against memory top. */ #include #include "libi386.h" #include "btxv86.h" ssize_t i386_copyin(const void *src, vm_offset_t dest, const size_t len) { if (dest + len >= memtop) { errno = EFBIG; return(-1); } bcopy(src, PTOV(dest), len); return(len); } ssize_t i386_copyout(const vm_offset_t src, void *dest, const size_t len) { if (src + len >= memtop) { errno = EFBIG; return(-1); } bcopy(PTOV(src), dest, len); return(len); } ssize_t i386_readin(const int fd, vm_offset_t dest, const size_t len) { - if (dest + len >= memtop) { + if (dest + len >= memtop_copyin) { errno = EFBIG; return(-1); } return (read(fd, PTOV(dest), len)); } Index: head/sys/boot/i386/libi386/libi386.h =================================================================== --- head/sys/boot/i386/libi386/libi386.h (revision 153588) +++ head/sys/boot/i386/libi386/libi386.h (revision 153589) @@ -1,115 +1,118 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ /* * i386 fully-qualified device descriptor. * Note, this must match the 'struct devdesc' declaration * in bootstrap.h. */ struct i386_devdesc { struct devsw *d_dev; int d_type; union { struct { int unit; int slice; int partition; void *data; } biosdisk; struct { int unit; void *data; } bioscd; struct { int unit; /* XXX net layer lives over these? */ } netif; } d_kind; }; int i386_getdev(void **vdev, const char *devspec, const char **path); char *i386_fmtdev(void *vdev); int i386_setcurrdev(struct env_var *ev, int flags, const void *value); extern struct devdesc currdev; /* our current device */ #define MAXDEV 31 /* maximum number of distinct devices */ /* exported devices XXX rename? */ extern struct devsw bioscd; extern struct devsw biosdisk; extern struct devsw pxedisk; extern struct fs_ops pxe_fsops; int bc_add(int biosdev); /* Register CD booted from. */ int bc_getdev(struct i386_devdesc *dev); /* return dev_t for (dev) */ int bc_bios2unit(int biosdev); /* xlate BIOS device -> bioscd unit */ int bc_unit2bios(int unit); /* xlate bioscd unit -> BIOS device */ u_int32_t bd_getbigeom(int bunit); /* return geometry in bootinfo format */ int bd_bios2unit(int biosdev); /* xlate BIOS device -> biosdisk unit */ int bd_unit2bios(int unit); /* xlate biosdisk unit -> BIOS device */ int bd_getdev(struct i386_devdesc *dev); /* return dev_t for (dev) */ ssize_t i386_copyin(const void *src, vm_offset_t dest, const size_t len); ssize_t i386_copyout(const vm_offset_t src, void *dest, const size_t len); ssize_t i386_readin(const int fd, vm_offset_t dest, const size_t len); struct preloaded_file; void bios_addsmapdata(struct preloaded_file *); void bios_getsmap(void); void bios_getmem(void); extern u_int32_t bios_basemem; /* base memory in bytes */ extern u_int32_t bios_extmem; /* extended memory in bytes */ -extern vm_offset_t memtop; +extern vm_offset_t memtop; /* last address of physical memory + 1 */ +extern vm_offset_t memtop_copyin; /* memtop less heap size for the cases */ + /* when heap is at the top of extended memory */ + /* for other cases - just the same as memtop */ int biospci_find_devclass(uint32_t class, int index); int biospci_write_config(uint32_t locator, int offset, int width, int val); int biospci_read_config(uint32_t locator, int offset, int width, uint32_t *val); void biosacpi_detect(); void smbios_detect(); void gateA20(void); int i386_autoload(void); int bi_getboothowto(char *kargs); void bi_setboothowto(int howto); vm_offset_t bi_copyenv(vm_offset_t addr); int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip, vm_offset_t *modulep, vm_offset_t *kernend); int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend); void pxe_enable(void *pxeinfo); Index: head/sys/boot/i386/loader/main.c =================================================================== --- head/sys/boot/i386/loader/main.c (revision 153588) +++ head/sys/boot/i386/loader/main.c (revision 153589) @@ -1,316 +1,317 @@ /*- * Copyright (c) 1998 Michael Smith * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * MD bootstrap main() and assorted miscellaneous * commands. */ #include #include #include #include #include "bootstrap.h" #include "libi386/libi386.h" #include "btxv86.h" #define KARGS_FLAGS_CD 0x1 #define KARGS_FLAGS_PXE 0x2 /* Arguments passed in from the boot1/boot2 loader */ static struct { u_int32_t howto; u_int32_t bootdev; u_int32_t bootflags; u_int32_t pxeinfo; u_int32_t res2; u_int32_t bootinfo; } *kargs; static u_int32_t initial_howto; static u_int32_t initial_bootdev; static struct bootinfo *initial_bootinfo; struct arch_switch archsw; /* MI/MD interface boundary */ static void extract_currdev(void); static int isa_inb(int port); static void isa_outb(int port, int value); void exit(int code); /* from vers.c */ extern char bootprog_name[], bootprog_rev[], bootprog_date[], bootprog_maker[]; /* XXX debugging */ extern char end[]; static void *heap_top; static void *heap_bottom; int main(void) { int i; /* Pick up arguments */ kargs = (void *)__args; initial_howto = kargs->howto; initial_bootdev = kargs->bootdev; initial_bootinfo = kargs->bootinfo ? (struct bootinfo *)PTOV(kargs->bootinfo) : NULL; /* * Initialise the heap as early as possible. Once this is done, malloc() is usable. */ bios_getmem(); #ifdef LOADER_BZIP2_SUPPORT - heap_top = PTOV(0x400000); - heap_bottom = PTOV(0x100000); + heap_top = PTOV(memtop_copyin); + memtop_copyin -= 0x300000; + heap_bottom = PTOV(memtop_copyin); #else heap_top = (void *)bios_basemem; heap_bottom = (void *)end; #endif setheap(heap_bottom, heap_top); /* * XXX Chicken-and-egg problem; we want to have console output early, but some * console attributes may depend on reading from eg. the boot device, which we * can't do yet. * * We can use printf() etc. once this is done. * If the previous boot stage has requested a serial console, prefer that. */ bi_setboothowto(initial_howto); if (initial_howto & RB_MULTIPLE) { if (initial_howto & RB_SERIAL) setenv("console", "comconsole vidconsole", 1); else setenv("console", "vidconsole comconsole", 1); } else if (initial_howto & RB_SERIAL) setenv("console", "comconsole", 1); else if (initial_howto & RB_MUTE) setenv("console", "nullconsole", 1); cons_probe(); /* * Initialise the block cache */ bcache_init(32, 512); /* 16k cache XXX tune this */ /* * Special handling for PXE and CD booting. */ if (kargs->bootinfo == 0) { /* * We only want the PXE disk to try to init itself in the below * walk through devsw if we actually booted off of PXE. */ if (kargs->bootflags & KARGS_FLAGS_PXE) pxe_enable(kargs->pxeinfo ? PTOV(kargs->pxeinfo) : NULL); else if (kargs->bootflags & KARGS_FLAGS_CD) bc_add(initial_bootdev); } /* * March through the device switch probing for things. */ for (i = 0; devsw[i] != NULL; i++) if (devsw[i]->dv_init != NULL) (devsw[i]->dv_init)(); printf("BIOS %dkB/%dkB available memory\n", bios_basemem / 1024, bios_extmem / 1024); if (initial_bootinfo != NULL) { initial_bootinfo->bi_basemem = bios_basemem / 1024; initial_bootinfo->bi_extmem = bios_extmem / 1024; } /* detect ACPI for future reference */ biosacpi_detect(); /* detect SMBIOS for future reference */ smbios_detect(); printf("\n"); printf("%s, Revision %s\n", bootprog_name, bootprog_rev); printf("(%s, %s)\n", bootprog_maker, bootprog_date); extract_currdev(); /* set $currdev and $loaddev */ setenv("LINES", "24", 1); /* optional */ bios_getsmap(); archsw.arch_autoload = i386_autoload; archsw.arch_getdev = i386_getdev; archsw.arch_copyin = i386_copyin; archsw.arch_copyout = i386_copyout; archsw.arch_readin = i386_readin; archsw.arch_isainb = isa_inb; archsw.arch_isaoutb = isa_outb; interact(); /* doesn't return */ /* if we ever get here, it is an error */ return (1); } /* * Set the 'current device' by (if possible) recovering the boot device as * supplied by the initial bootstrap. * * XXX should be extended for netbooting. */ static void extract_currdev(void) { struct i386_devdesc new_currdev; int major, biosdev = -1; /* Assume we are booting from a BIOS disk by default */ new_currdev.d_dev = &biosdisk; /* new-style boot loaders such as pxeldr and cdldr */ if (kargs->bootinfo == 0) { if ((kargs->bootflags & KARGS_FLAGS_CD) != 0) { /* we are booting from a CD with cdboot */ new_currdev.d_dev = &bioscd; new_currdev.d_kind.bioscd.unit = bc_bios2unit(initial_bootdev); } else if ((kargs->bootflags & KARGS_FLAGS_PXE) != 0) { /* we are booting from pxeldr */ new_currdev.d_dev = &pxedisk; new_currdev.d_kind.netif.unit = 0; } else { /* we don't know what our boot device is */ new_currdev.d_kind.biosdisk.slice = -1; new_currdev.d_kind.biosdisk.partition = 0; biosdev = -1; } } else if ((initial_bootdev & B_MAGICMASK) != B_DEVMAGIC) { /* The passed-in boot device is bad */ new_currdev.d_kind.biosdisk.slice = -1; new_currdev.d_kind.biosdisk.partition = 0; biosdev = -1; } else { new_currdev.d_kind.biosdisk.slice = (B_ADAPTOR(initial_bootdev) << 4) + B_CONTROLLER(initial_bootdev) - 1; new_currdev.d_kind.biosdisk.partition = B_PARTITION(initial_bootdev); biosdev = initial_bootinfo->bi_bios_dev; major = B_TYPE(initial_bootdev); /* * If we are booted by an old bootstrap, we have to guess at the BIOS * unit number. We will loose if there is more than one disk type * and we are not booting from the lowest-numbered disk type * (ie. SCSI when IDE also exists). */ if ((biosdev == 0) && (B_TYPE(initial_bootdev) != 2)) /* biosdev doesn't match major */ biosdev = 0x80 + B_UNIT(initial_bootdev); /* assume harddisk */ } new_currdev.d_type = new_currdev.d_dev->dv_type; /* * If we are booting off of a BIOS disk and we didn't succeed in determining * which one we booted off of, just use disk0: as a reasonable default. */ if ((new_currdev.d_type == biosdisk.dv_type) && ((new_currdev.d_kind.biosdisk.unit = bd_bios2unit(biosdev)) == -1)) { printf("Can't work out which disk we are booting from.\n" "Guessed BIOS device 0x%x not found by probes, defaulting to disk0:\n", biosdev); new_currdev.d_kind.biosdisk.unit = 0; } env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev), i386_setcurrdev, env_nounset); env_setenv("loaddev", EV_VOLATILE, i386_fmtdev(&new_currdev), env_noset, env_nounset); } COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot); static int command_reboot(int argc, char *argv[]) { int i; for (i = 0; devsw[i] != NULL; ++i) if (devsw[i]->dv_cleanup != NULL) (devsw[i]->dv_cleanup)(); printf("Rebooting...\n"); delay(1000000); __exit(0); } /* provide this for panic, as it's not in the startup code */ void exit(int code) { __exit(code); } COMMAND_SET(heap, "heap", "show heap usage", command_heap); static int command_heap(int argc, char *argv[]) { mallocstats(); printf("heap base at %p, top at %p, upper limit at %p\n", heap_bottom, sbrk(0), heap_top); return(CMD_OK); } /* ISA bus access functions for PnP, derived from */ static int isa_inb(int port) { u_char data; if (__builtin_constant_p(port) && (((port) & 0xffff) < 0x100) && ((port) < 0x10000)) { __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port))); } else { __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); } return(data); } static void isa_outb(int port, int value) { u_char al = value; if (__builtin_constant_p(port) && (((port) & 0xffff) < 0x100) && ((port) < 0x10000)) { __asm __volatile("outb %0,%1" : : "a" (al), "id" ((u_short)(port))); } else { __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); } }