diff options
-rw-r--r-- | sys/i386/boot/cdboot/Makefile | 114 | ||||
-rw-r--r-- | sys/i386/boot/cdboot/asm.S | 278 | ||||
-rw-r--r-- | sys/i386/boot/cdboot/bios.S | 411 | ||||
-rw-r--r-- | sys/i386/boot/cdboot/boot.c | 393 | ||||
-rw-r--r-- | sys/i386/boot/cdboot/boot.h | 180 | ||||
-rw-r--r-- | sys/i386/boot/cdboot/cdrom.c | 356 | ||||
-rw-r--r-- | sys/i386/boot/cdboot/io.c | 287 | ||||
-rw-r--r-- | sys/i386/boot/cdboot/malloc.c | 179 |
8 files changed, 2198 insertions, 0 deletions
diff --git a/sys/i386/boot/cdboot/Makefile b/sys/i386/boot/cdboot/Makefile new file mode 100644 index 0000000..514b227 --- /dev/null +++ b/sys/i386/boot/cdboot/Makefile @@ -0,0 +1,114 @@ +# $Id$ +# + +PROG= boot +# Order is very important on the SRCS line for this prog +SRCS= start.S table.c boot2.S boot.c asm.S bios.S serial.S +SRCS+= probe_keyboard.c io.c cdrom.c malloc.c + +.PATH: ${.CURDIR}/../biosboot + +BINDIR= /usr/mdec +BINMODE= 444 +CFLAGS= -O2 -malign-functions=0 -malign-jumps=0 -malign-loops=0 \ + -mno-486 \ + -DDO_BAD144 -DBOOTWAIT=${BOOTWAIT} -DTIMEOUT=${TIMEOUT} +CFLAGS+= -DBOOTSEG=${BOOTSEG} -DBOOTSTACK=${BOOTSTACK} +CFLAGS+= -I${.CURDIR}/../../.. -I${.CURDIR}/../biosboot +CFLAGS+= ${CWARNFLAGS} +#CFLAGS+= -DDEBUG + +# Probe the keyboard and use the serial console if the keyboard isn't found. +.if defined(BOOT_PROBE_KEYBOARD) +CFLAGS+= -DPROBE_KEYBOARD +.endif + +# Probe the keyboard lock and use the serial console if the keyboard is locked. +.if defined(BOOT_PROBE_KEYBOARD_LOCK) +CFLAGS+= -DPROBE_KEYBOARD_LOCK +.endif + +# Force use of the serial console. +.if defined(BOOT_FORCE_COMCONSOLE) +CFLAGS+= -DFORCE_COMCONSOLE +.endif + +# By default, if a serial port is going to be used as console, use COM1 +# (aka /dev/ttyd0). +BOOT_COMCONSOLE_PORT?=0x3F8 +CFLAGS+= -DCOMCONSOLE=${BOOT_COMCONSOLE_PORT} + +BOOT_COMCONSOLE_SPEED?=9600 +CFLAGS+= -DCONSPEED=${BOOT_COMCONSOLE_SPEED} + +# Enable code to take the default boot string from a fixed location on the +# disk. See nextboot(8) and README.386BSD for more info. +#CFLAGS+= -DNAMEBLOCK +#CFLAGS+= -DNAMEBLOCK_WRITEBACK + +# Bias the conversion from the BIOS drive number to the FreeBSD unit number +# for hard disks. This may be useful for people booting in a mixed IDE/SCSI +# environment (set BOOT_HD_BIAS to the number of IDE drives). +#CFLAGS+= -DBOOT_HD_BIAS=1 +# +# Details: this only applies if BOOT_HD_BIAS > 0. If the BIOS drive number +# for the boot drive is >= BOOT_HD_BIAS, then the boot drive is assumed to +# be SCSI and have unit number (BIOS_drive_number - BOOT_HD_BIAS). E.g., +# BOOT_HD_BIAS=1 makes BIOS drive 1 correspond to 1:sd(0,a) instead of +# 1:wd(1,a). If `sd' is given explicitly, then the drive is assumed to be +# SCSI and have BIOS drive number (sd_unit_number + BOOT_HD_BIAS). E.g., +# BOOT_HD_BIAS=1 makes sd(0,a) correspond to 1:sd(0,a) instead of 0:sd(0,a). + +CLEANFILES+= boot.nohdr boot.strip boot1 boot2 sizetest +LDFLAGS+= -N -T 0 -nostdlib +#LINKS= ${BINDIR}/sdboot ${BINDIR}/wdboot\ +# ${BINDIR}/sdboot ${BINDIR}/fdboot\ +# ${BINDIR}/bootsd ${BINDIR}/bootwd\ +# ${BINDIR}/bootsd ${BINDIR}/bootfd +NOSHARED= YES +NOMAN= +STRIP= + +# tunable timeout parameter, waiting for keypress, calibrated in ms +BOOTWAIT?= 5000 +# tunable timeout during string input, calibrated in ms +#TIMEOUT?= 30000 + +# Location that boot2 is loaded at +BOOTSEG= 0x1000 + +# Offset in BOOTSEG for the top of the stack, keep this 16 byte aligned +BOOTSTACK= 0xFFF0 + +boot.strip: boot + cp -p boot boot.strip + strip boot.strip + size boot.strip + +boot.nohdr: boot.strip + dd if=boot.strip of=boot.nohdr ibs=32 skip=1 obs=1024b + ls -l boot.nohdr + +boot1: boot.nohdr + dd if=boot.nohdr of=boot1 bs=512 count=1 + +boot2: boot.nohdr + dd if=boot.nohdr of=boot2 bs=512 skip=1 + @dd if=boot2 skip=14 of=sizetest 2> /dev/null + @if [ -s sizetest ] ; then \ + echo "boot2 is too big" >&2 ; \ + rm boot2 ; \ + exit 2 ; \ + fi + +boot.img: boot.nohdr + dd if=boot.nohdr of=boot.img bs=1440k count=1 conv=sync + +all: boot.img + +install: + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE}\ + boot.img ${DESTDIR}${BINDIR}/cdboot + +.include <bsd.kern.mk> +.include <bsd.prog.mk> diff --git a/sys/i386/boot/cdboot/asm.S b/sys/i386/boot/cdboot/asm.S new file mode 100644 index 0000000..e689817 --- /dev/null +++ b/sys/i386/boot/cdboot/asm.S @@ -0,0 +1,278 @@ +/* + * 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, Revision 2.2 92/04/04 11:34:13 rpd + * $Id: asm.S,v 1.9 1996/03/08 07:27:52 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. +*/ + + .file "asm.s" + +#include "asm.h" + + +CR0_PE_ON = 0x1 +CR0_PE_OFF = 0xfffffffe + + .text + +/* + * + * real_to_prot() + * transfer from real mode to protected mode. + */ + +ENTRY(real_to_prot) + /* guarantee that interrupt is disabled when in prot mode */ + cli + + /* load the gdtr */ + addr32 + data32 + lgdt EXT(Gdtr) + + /* set the PE bit of CR0 */ + mov %cr0, %eax + + data32 + or $CR0_PE_ON, %eax + mov %eax, %cr0 + + /* + * make intrasegment jump to flush the processor pipeline and + * reload CS register + */ + data32 + ljmp $0x18, $xprot +xprot: + + /* + * we are in USE32 mode now + * set up the protected mode segment registers : DS, SS, ES, FS + */ + movw $0x20, %ax /* data segment */ + mov %ax, %ds /* gas would waste a prefix byte for movw */ + mov %ax, %ss + mov %ax, %es + movw $0x10, %ax /* flat segment */ + mov %ax, %fs + +#ifdef BDE_DEBUGGER + /* load idtr so we can debug */ + lidt EXT(Idtr_prot) +#endif + + ret + +/* + * + * prot_to_real() + * transfer from protected mode to real mode + * + */ + +ENTRY(prot_to_real) + + /* Prepare %ax while we're still in a mode that gas understands. */ + movw $0x30, %ax + + /* Change to use16 mode. */ + ljmp $0x28, $x16 +x16: + + mov %ax, %ds + mov %ax, %ss + mov %ax, %es + mov %ax, %fs + + /* clear the PE bit of CR0 */ + mov %cr0, %eax + data32 + and $CR0_PE_OFF, %eax + mov %eax, %cr0 + + /* + * make intersegment jmp to flush the processor pipeline + * and reload CS register + */ + data32 + ljmp $BOOTSEG, $xreal +xreal: + + /* + * we are in real mode now + * set up the real mode segment registers : DS, SS, ES, FS + */ + mov %cs, %ax + mov %ax, %ds + mov %ax, %ss + mov %ax, %es + mov %ax, %fs + +#ifdef BDE_DEBUGGER + /* load idtr so we can debug */ + addr32 + data32 + lidt EXT(Idtr_real) +#endif + + data32 + ret + +/* + * startprog(phyaddr) + * start the program on protected mode where phyaddr is the entry point + * + * XXX This whole mess should go away and we should run the boot code in + * flat 32 bit mode with it linked -T BOOTSEG. See the netboot code for + * how this is done. + */ + +ENTRY(startprog) + push %ebp + mov %esp, %ebp + movl %esp, %eax /* Use eax as the old stack pointer */ + + /* convert the current stack to a 32 bit flat model */ + movw $0x10, %bx + mov %bx, %ss + addl $(BOOTSEG<<4),%esp + + /* copy the arguments from the old stack to the new stack */ + pushl 0x14(%eax) /* &bootinfo */ + pushl $0 /* was &nfsdiskless */ + pushl $0 /* was esym */ + pushl $0 /* was cyloffset */ + pushl 0x10(%eax) /* bootdev */ + pushl 0x0C(%eax) /* howto */ + movl $(ourreturn),%ebx + addl $(BOOTSEG<<4),%ebx /* Fix it up for flat segments */ + pushl %ebx /* our return address */ + + /* push on our entry address */ + pushl $0x08 /* segment selector */ + pushl 0x08(%eax) /* kernel entry address */ + + /* convert over the other data segs */ + movw $0x10, %bx + mov %bx, %ds + mov %bx, %es + + /* convert the PC (and code seg) */ + lret +ourreturn: + /* For now there is not much we can do, just lock in a loop */ + jmp ourreturn + +/* + * + * pbzero( dst, cnt) + * where src is a virtual address and dst is a physical address + */ + +ENTRY(pbzero) + push %ebp + mov %esp, %ebp + push %es + push %esi + push %edi + push %ecx + + cld + + /* set %es to point at the flat segment */ + movw $0x10, %ax + mov %ax, %es + + mov 0x8(%ebp), %edi /* destination */ + mov 0xc(%ebp), %ecx /* count */ + xorl %eax, %eax /* value 0 */ + + rep + stosb + + pop %ecx + pop %edi + pop %esi + pop %es + pop %ebp + + ret +/* + * pcpy(src, dst, cnt) + * where src is a virtual address and dst is a physical address + */ + +ENTRY(pcpy) + push %ebp + mov %esp, %ebp + push %es + push %esi + push %edi + push %ecx + + cld + + /* set %es to point at the flat segment */ + movw $0x10, %ax + mov %ax, %es + + mov 0x8(%ebp), %esi /* source */ + mov 0xc(%ebp), %edi /* destination */ + mov 0x10(%ebp), %ecx /* count */ + + rep + movsb + + pop %ecx + pop %edi + pop %esi + pop %es + pop %ebp + + ret diff --git a/sys/i386/boot/cdboot/bios.S b/sys/i386/boot/cdboot/bios.S new file mode 100644 index 0000000..99c8c94 --- /dev/null +++ b/sys/i386/boot/cdboot/bios.S @@ -0,0 +1,411 @@ +/* + * 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, Revision 2.2 92/04/04 11:34:26 rpd + * $Id$ + */ + +/* + 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. +*/ + +/* + * Extensions for El Torito CD-ROM booting: + * + * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO + * Copyright © 1997 interface business GmbH, Dresden. + * All rights reserved. + * + * This code has been written by Jörg Wunsch, Dresden. + * Direct comments to <joerg_wunsch@interface-business.de>. + * + * 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(S) ``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(S) 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. + * + */ + + .file "bios.s" + +#include "asm.h" + .text + +/* + * int + * getbootspec(struct specpacket *offset) + * + * Read CD-ROM boot specification packet to "offset". + */ +ENTRY(getbootspec) + push %ebp + mov %esp, %ebp + + push %esi + push %ebx + + movw 0x8(%ebp), %si + mov $0x7f, %edx + + /* prot_to_real will set %es to BOOTSEG */ + call EXT(prot_to_real) /* enter real mode */ + movw $0x4b01, %ax /* (do not) terminate disk emulation */ + movb $0x7f, %dl /* any drive */ + + sti + int $0x13 + cli + + /* save return value (actually movw %ax, %bx) */ + mov %eax, %ebx + + data32 + call EXT(real_to_prot) /* back to protected mode */ + + xor %eax, %eax + movb %bh, %al /* return value in %ax */ + + pop %ebx + pop %esi + pop %ebp + + ret + + +/* + * int + * biosreadlba(struct daddrpacket *daddr) + * Read sectors using the BIOS "read extended" function + * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory + * Call with %ah = 0x42 + * %dl = drive (0x0 for floppy disk, or emulated CD) + * %ds:%si = ptr to disk address packet + * Return: + * %ah = 0x0 on success; err code on failure + */ + +ENTRY(biosreadlba) + push %ebp + mov %esp, %ebp + + push %ebx + push %esi + + movw 8(%ebp), %si + movl $0, %edx /* emulated CD is always drive 0 */ + + /* prot_to_real will set %es to BOOTSEG */ + call EXT(prot_to_real) /* enter real mode */ + movw $0x4200, %ax /* subfunction */ + movb $0, %dl + + sti + int $0x13 + cli + + /* save return value (actually movw %ax, %bx) */ + mov %eax, %ebx + + data32 + call EXT(real_to_prot) /* back to protected mode */ + + xor %eax, %eax + movb %bh, %al /* return value in %ax */ + + pop %esi + pop %ebx + pop %ebp + + ret + +/* + * putc(ch) + * BIOS call "INT 10H Function 0Eh" to write character to console + * Call with %ah = 0x0e + * %al = character + * %bh = page + * %bl = foreground color ( graphics modes) + */ + + +ENTRY(putc) + push %ebp + mov %esp, %ebp + push %ebx + push %esi + push %edi + + movb 0x8(%ebp), %cl + + call EXT(prot_to_real) + + data32 + mov $0x1, %ebx /* %bh=0, %bl=1 (blue) */ + movb $0xe, %ah + movb %cl, %al + sti + int $0x10 /* display a byte */ + cli + + data32 + call EXT(real_to_prot) + + pop %edi + pop %esi + pop %ebx + pop %ebp + ret + + +/* + * getc() + * BIOS call "INT 16H Function 00H" to read character from keyboard + * Call with %ah = 0x0 + * Return: %ah = keyboard scan code + * %al = ASCII character + */ + +ENTRY(getc) + push %ebp + mov %esp, %ebp + push %ebx /* save %ebx */ + push %esi + push %edi + + call EXT(prot_to_real) + + movb $0x0, %ah + sti + int $0x16 + cli + + movb %al, %bl /* real_to_prot uses %eax */ + + data32 + call EXT(real_to_prot) + + xor %eax, %eax + movb %bl, %al + + pop %edi + pop %esi + pop %ebx + pop %ebp + ret +/* + * ischar() + * if there is a character pending, return it; otherwise return 0 + * BIOS call "INT 16H Function 01H" to check whether a character is pending + * Call with %ah = 0x1 + * Return: + * If key waiting to be input: + * %ah = keyboard scan code + * %al = ASCII character + * Zero flag = clear + * else + * Zero flag = set + */ +ENTRY(ischar) + push %ebp + mov %esp, %ebp + push %ebx + push %esi + push %edi + + call EXT(prot_to_real) /* enter real mode */ + + xor %ebx, %ebx + movb $0x1, %ah + sti + int $0x16 + cli + data32 + jz nochar + movb %al, %bl + +nochar: + data32 + call EXT(real_to_prot) + + xor %eax, %eax + movb %bl, %al + + pop %edi + pop %esi + pop %ebx + pop %ebp + ret + +/* + * + * get_diskinfo(): return a word that represents the + * max number of sectors and heads and drives for this device + * + */ + +ENTRY(get_diskinfo) + push %ebp + mov %esp, %ebp + push %ebx + push %esi + push %edi + + movb 0x8(%ebp), %dl /* diskinfo(drive #) */ + call EXT(prot_to_real) /* enter real mode */ + + movb $0x8, %ah /* ask for disk info */ + + sti + int $0x13 + cli + + jnc ok + /* + * Urk. Call failed. It is not supported for floppies by old BIOS's. + * Guess it's a 15-sector floppy. + */ + subb %ah, %ah /* %ax = 0 */ + movb %al, %al + movb %ah, %bh /* %bh = 0 */ + movb $2, %bl /* %bl bits 0-3 = drive type, + bit 2 = 1.2M */ + movb $79, %ch /* max track */ + movb $15, %cl /* max sector */ + movb $1, %dh /* max head */ + movb $1, %dl /* # floppy drives installed */ + /* es:di = parameter table */ + /* carry = 0 */ +ok: + + data32 + call EXT(real_to_prot) /* back to protected mode */ + + /* + * form a longword representing all this gunk: + * 6 bit zero + * 10 bit max cylinder (0 based) + * 8 bit max head (0 based) + * 8 bit zero + * 6 bit max sector (1 based) = # sectors + */ + movb %cl, %al /* Upper two bits of cylinder count */ + andl $192,%eax + leal 0(,%eax,4),%eax /* << 2 */ + movb %ch, %al /* Lower 8 bits */ + sall $16,%eax /* << 16 */ + movb %dh, %ah /* max head */ + andb $0x3f, %cl /* mask of cylinder gunk */ + movb %cl, %al /* max sector (and # sectors) */ + + pop %edi + pop %esi + pop %ebx + pop %ebp + ret + +/* + * + * memsize(i) : return the memory size in KB. i == 0 for conventional memory, + * i == 1 for extended memory + * BIOS call "INT 12H" to get conventional memory size + * BIOS call "INT 15H, AH=88H" to get extended memory size + * Both have the return value in AX. + * + */ + +ENTRY(memsize) + push %ebp + mov %esp, %ebp + push %ebx + push %esi + push %edi + + mov 8(%ebp), %ebx + + call EXT(prot_to_real) /* enter real mode */ + + cmpb $0x1, %bl + data32 + je xext + + sti + int $0x12 + cli + data32 + jmp xdone + +xext: movb $0x88, %ah + sti + int $0x15 + cli + +xdone: + pushl $0 /* actually pushw $0 */ + pushl %eax /* actually pushw %ax */ + + data32 + call EXT(real_to_prot) + + pop %eax + pop %edi + pop %esi + pop %ebx + pop %ebp + ret diff --git a/sys/i386/boot/cdboot/boot.c b/sys/i386/boot/cdboot/boot.c new file mode 100644 index 0000000..0354cc1 --- /dev/null +++ b/sys/i386/boot/cdboot/boot.c @@ -0,0 +1,393 @@ +/* + * 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$ + */ + + +/* + 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. +*/ + +/* + * Extensions for El Torito CD-ROM booting: + * + * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO + * Copyright © 1997 interface business GmbH, Dresden. + * All rights reserved. + * + * This code was written by Jörg Wunsch, Dresden. + * Direct comments to <joerg_wunsch@interface-business.de>. + * + * 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(S) ``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(S) 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 <sys/param.h> +#include "boot.h" +#include <a.out.h> +#include <sys/reboot.h> +#include <machine/bootinfo.h> +#ifdef PROBE_KEYBOARD_LOCK +#include <machine/cpufunc.h> +#endif + +#define ouraddr (BOOTSEG << 4) /* XXX */ + +int loadflags; + +/* + * XXX + * By now, only "cd". How do we learn from the BIOS we've been booted off + * an ATAPI CD-ROM? Do the non-{cd,wcd} drivers implement El Torito booting + * at all? + */ +static int maj = 6; +static struct specpacket spkt = { 0x13 }; +static char *name; +static char namebuf[128]; +static struct bootinfo bootinfo; + +static void getbootdev(char *ptr, int *howto); +static void loadprog(void); + +/* NORETURN */ +void +boot(int drive) +{ + int ret, i; + +#ifdef PROBE_KEYBOARD + if (probe_keyboard()) { + init_serial(); + loadflags |= RB_SERIAL; + printf("\nNo keyboard found."); + } +#endif + +#ifdef PROBE_KEYBOARD_LOCK + if (!(inb(0x64) & 0x10)) { + init_serial(); + loadflags |= RB_SERIAL; + printf("\nKeyboard locked."); + } +#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 */ + + /* + * XXX + * Do we need to defer this until we can relinguish the + * BIOS emulation? + */ + + for(ret = 0; ret < N_BIOS_GEOM; ret ++) + bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80); + + bootinfo.bi_basemem = memsize(0); + bootinfo.bi_extmem = memsize(1); + bootinfo.bi_memsizes_valid = 1; + + gateA20(); + + ret = getbootspec(&spkt); + if (ret != 0) { + printf("Your BIOS int 0x13 extensions seem to be disabled.\n" + "It's impossible to boot a CD-ROM without them.\n" + "(BIOS int 0x13 fn 0x4b01 yielded error %d)\n", + ret); + while (1) + ; + } + + if (devopen(sessionstart) == -1) + printf("Warning: cannot open default session.\n" + "Maybe your BIOS int 0x13 extensions are disabled?\n" + "You need them in order to boot a CD-ROM.\n"); + + for (;;) { + + /* + * The El Torito specification stinks. Not only this + * crappy idea of `emulation booting' (and at least + * earlier versions of the AHA-2940 BIOS didn't + * implement anything else than floppy emulation + * booting), but note also that there's absolutely no + * way via the BIOS to obtain the starting LBA of your + * session. All you can get ahold of is the LBA of + * that funny emulated disk. Since this one just + * happens to be a file hidden inside the ISO9660 + * filesystem, it is located at a varying offset from + * the start of the session. We therefore allow to + * specify the starting block of the session to use in + * the boot string, so the operator can specify the + * session to boot from. However, (s)he needs to know + * the RBA for the session from the CD-ROM TOC. + */ + DPRINTF(("using session at sector %d\n", sessionstart)); + + name = "/kernel"; + printf("\n>> FreeBSD CD-ROM BOOT\n" + "Usage: [@%d]%s[-abcCdghrsv]\n" + "Use ? for file list or press Enter for defaults\n" + "\nBoot: ", + sessionstart, name); + + loadflags &= RB_SERIAL; /* clear all, but leave serial console */ + loadflags |= RB_CDROM; /* ...and default to CD-ROM root. */ + + getbootdev(namebuf, &loadflags); + + DPRINTF(("Selected: name=`%s', loadflags=0x%x\n", + name, loadflags)); + + ret = openrd(name); + + DPRINTF(("openrd() = %d\n", ret)); + + if (ret != 0) { + if (ret > 0) + printf("Can't find %s\n", name); + continue; + } + loadprog(); + } +} + +static void +loadprog(void) +{ + struct exec head; + u_int32_t startaddr, addr, bootdev; + int i; + unsigned pad; + + seek(0); + if (read((void *)&head, sizeof(head)) == -1 || + N_BADMAG(head)) { + printf("Invalid format!\n"); + return; + } + + /* + * 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 CD-ROM [@%d]%s @ 0x%x\n", sessionstart, 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 */ + seek(N_TXTOFF(head)); + if (xread((void *)addr, head.a_text) == -1) + return; + addr += head.a_text; + + /* Pad to a page boundary. */ + pad = (unsigned)addr & PAGE_MASK; + if (pad != 0) { + pad = PAGE_SIZE - pad; + pbzero((void *)addr, pad); + addr += pad; + } + + /* load the initialised data after the text */ + printf("data=0x%x ", head.a_data); + if (xread((void *)addr, head.a_data) == -1) + return; + 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); + if (xread((void *)addr, head.a_syms) == -1) + return; + addr += head.a_syms; + + /* Load the string table size */ + if (read((void *)&i, sizeof(int)) == -1) + return; + 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); + if (xread((void *)addr, i) == -1) + return; + addr += i; + + bootinfo.bi_esymtab = addr; + + /* XXX what else can we say about a CD-ROM? */ + bootdev = MAKEBOOTDEV(maj, 0, 0, 0, 0); + + 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); +} + +static 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(); + continue; + } + if (c == 'g') + *howto |= RB_GDB; + 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; + } + } + } +} diff --git a/sys/i386/boot/cdboot/boot.h b/sys/i386/boot/cdboot/boot.h new file mode 100644 index 0000000..b71f457 --- /dev/null +++ b/sys/i386/boot/cdboot/boot.h @@ -0,0 +1,180 @@ +/* + * 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, Revision 2.2 92/04/04 11:35:03 rpd + * $Id$ + */ +/* + * Extensions for El Torito CD-ROM booting: + * + * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO + * Copyright © 1997 interface business GmbH, Dresden. + * All rights reserved. + * + * This code has been written by Jörg Wunsch, Dresden. + * Direct comments to <joerg_wunsch@interface-business.de>. + * + * 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(S) ``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(S) 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 <sys/param.h> +#include <sys/time.h> + +/* + * Specification packet per El Torito, BIOS int 0x13 fn 0x4b00/0x4b01 + */ +struct specpacket +{ + u_char size; /* must be 0x13 */ + u_char mediatype; /* + * 0 - no emulation + * 1 - 1.2 MB floppy + * 2 - 1.44 MB floppy + * 3 - 2.88 MB floppy + * 4 - hard disk C: + */ + u_char drvno; /* emulated drive number */ + u_char ctrlindx; /* controller index, see El Torito */ + u_int32_t lba; /* LBA of emulated disk drive */ + u_int16_t devspec; /* device specification, see El Torito */ + u_int16_t ubufseg; /* user buffer segment */ + u_int16_t loadseg; /* load segment; 0 => use BIOS default 0x7c0 */ + u_int16_t seccnt; /* number of auto-loaded (virtual) sectors */ + u_char cyls; /* same values as in int 0x13, fn 8 */ + u_char secs; + u_char heads; +}; + +/* + * Disk address packet for extended BIOS int 0x13 fn's 0x41...0x48. + */ +struct daddrpacket +{ + u_char size; /* size of daddrpacket, must be 0x10 */ + u_char reserved1; + u_char nblocks; /* + * number of 512-byte blocks to transfer, + * must be <= 127 + */ + u_char reserved2; + u_int16_t boffs; /* bseg:boffs denominate the transfer buffer */ + u_int16_t bseg; + u_int32_t lba; /* actually a 64-bit type, but 64-bit arith */ + u_int32_t lbahigh; /* is expensive, and we don't really need it */ +}; + +#ifdef DEBUG +# define DPRINTF(x) printf x +#else +# define DPRINTF(x) +#endif + + +/* asm.S */ +#if ASM_ONLY +void real_to_prot(void); +void prot_to_real(void); +#endif +void startprog(unsigned int physaddr, int howto, int bootdev, + /* XXX struct bootinfo * */ unsigned int bootinfo); +void pbzero(void *dst, size_t count); +void pcpy(const void *src, void *dst, size_t count); + +/* bios.S */ + +int biosread(int dev, int cyl, int head, int sec, int nsec, void *offset); +int getbootspec(struct specpacket *offset); +int biosreadlba(struct daddrpacket *daddr); +void putc(int c); +int getc(void); +int ischar(void); +int get_diskinfo(int drive); +int memsize(int extended); + +/* boot.c */ +extern int loadflags; + +void boot(int drive); + +/* boot2.S */ +void boot2(void); + +/* cdrom.c */ +extern u_int32_t sessionstart; + +int devopen(u_int32_t session); +void seek(u_int32_t offs); +int read(u_char *addr, size_t size); +int xread(u_char *addr, size_t size); +int openrd(char *name); + +/* io.c */ +void gateA20(void); +void printf(const char *format, ...); +void putchar(int c); +void delay1ms(void); +int gets(char *buf); +int strncasecmp(const char *s1, const char *s2, size_t s); +void bcopy(const void *from, void *to, size_t len); +void twiddle(void); + +/* probe_keyboard.c */ +int probe_keyboard(void); + +/* serial.S */ +void serial_putc(int ch); +int serial_getc(void); +int serial_ischar(void); +void init_serial(void); + +/* table.c */ +extern char *devs[]; +extern unsigned long tw_chars; + +/* malloc.c */ +void *malloc(size_t size); +void free(void *chunk); + +/* linker stuff */ +extern void end; diff --git a/sys/i386/boot/cdboot/cdrom.c b/sys/i386/boot/cdboot/cdrom.c new file mode 100644 index 0000000..03081d9 --- /dev/null +++ b/sys/i386/boot/cdboot/cdrom.c @@ -0,0 +1,356 @@ +/* + * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO + * Copyright © 1997 interface business GmbH, Dresden. + * All rights reserved. + * + * This code was written by Jörg Wunsch, Dresden. + * Direct comments to <joerg_wunsch@interface-business.de>. + * + * 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(S) ``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(S) 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. + * + * $Id$ + */ + + +#include "boot.h" + +#include <isofs/cd9660/iso.h> + +#define BLKSIZE 2048 /* CD-ROM data block size */ +#define BIOSSEC 512 /* BIOS sector size */ + +#define CD2LBA(rba) ((rba) << 2) /* CD-ROM relative block to BIOS LBA */ + +u_int32_t sessionstart; + +static struct iso_primary_descriptor pdesc; + +static char *rootdirbuf; +static size_t rootdirsize; +static char xbuf[BLKSIZE]; +static u_int32_t curblk, startblk, filesize, offset; + +static int bread(u_int32_t rba, size_t nblks, void *buf); +static void badread(const char *msg, u_int32_t blkno); +static struct iso_directory_record *find(const char *path, int list_only); +static int iread(u_char *buf, size_t len, + void (*copyfun)(const void *src, void *dst, size_t size)); + +static struct daddrpacket dpkt = { 0x10 }; + +int +devopen(u_int32_t session) +{ + int rv; + u_int32_t rootdirblk; + struct iso_directory_record *rootdirp; + + if ((rv = bread(session + 16, 1, &pdesc)) != 0) { + printf("Error reading primary ISO descriptor: %d\n", rv); + return -1; + } + rootdirp = (struct iso_directory_record *)pdesc.root_directory_record; + rootdirblk = isonum_733(rootdirp->extent); + rootdirsize = isonum_733(rootdirp->size); + + /* just in case, round up */ + rootdirsize = (rootdirsize + BLKSIZE - 1) & ~(BLKSIZE - 1); + + if (rootdirbuf != NULL) + free(rootdirbuf); + if ((rootdirbuf = malloc(rootdirsize)) == 0) { + printf("Cannot allocate memory for the root " + "directory buffer.\n"); + return -1; + } + if ((rv = bread(rootdirblk, rootdirsize / BLKSIZE, rootdirbuf)) + != 0) { + printf("Error reading root directory: %d\n", rv); + return -1; + } + + DPRINTF(("Root directory is 0x%x bytes @ %d\n", + rootdirsize, rootdirblk)); + + return 0; +} + +static int +bread(u_int32_t rba, size_t nblks, void *buf) +{ + int i, rv; + + for (i = 0, rv = -1; rv != 0 && i < 3; i++) { + dpkt.nblocks = nblks * (BLKSIZE / BIOSSEC); + dpkt.boffs = (u_int16_t)((int)buf & 0xffff); + dpkt.bseg = BOOTSEG; + dpkt.lba = CD2LBA(rba); + +#ifdef DEBUG_VERBOSE + DPRINTF(("Calling biosreadlba(%d blocks, lba %d) = ", + dpkt.nblocks, dpkt.lba)); +#endif + + rv = biosreadlba(&dpkt); + +#ifdef DEBUG_VERBOSE + DPRINTF(("%d\n", rv)); +#endif + } + return rv; +} + + +void +seek(u_int32_t offs) +{ + offset = offs; +} + +static void +badread(const char *msg, u_int32_t blkno) +{ + printf("Error reading block %d from CD-ROM: %s\n", + blkno, msg); +} + +static __inline size_t +minlen(size_t a, size_t b) +{ + return a < b? a: b; +} + +/* + * Internal form of read()/xread(). + */ +static int +iread(u_char *buf, size_t len, + void (*copyfun)(const void *src, void *dst, size_t size)) +{ + u_int32_t newblk, ptr; + size_t bsize; + + newblk = offset / BLKSIZE + startblk; + + if (newblk != curblk) { + if (offset + len >= filesize) { + badread("access beyond file limit", newblk); + return -1; + } + if (bread(newblk, 1, xbuf)) { + badread("BIOS read error", newblk); + return -1; + } + curblk = newblk; + } + ptr = offset & (BLKSIZE - 1); + if (ptr > 0) { + /* initial short transfer */ + bsize = minlen(BLKSIZE - ptr, len); + copyfun(xbuf + ptr, buf, bsize); + buf += bsize; + len -= bsize; + offset += bsize; + } + for (; len > 0; len -= bsize) { + bsize = minlen(len, BLKSIZE); + newblk = offset / BLKSIZE + startblk; + + if (newblk != curblk) { + if (offset + bsize > filesize) { + badread("access beyond file limit", newblk); + return -1; + } + if (bread(newblk, 1, xbuf)) { + badread("BIOS read error", newblk); + return -1; + } + curblk = newblk; + } + copyfun(xbuf, buf, bsize); + buf += bsize; + offset += bsize; + } + return 0; +} + +int +read(u_char *buf, size_t len) +{ + DPRINTF(("read(0x%x, %d)\n", (int)buf, len)); + return iread(buf, len, bcopy); +} + +int +xread(u_char *buf, size_t len) +{ + DPRINTF(("xread(0x%x, %d)\n", (int)buf, len)); + return iread(buf, len, pcpy); +} + +/* + * XXX Todo: + * Use RR attributes if present + */ +static struct iso_directory_record * +find(const char *path, int list_only) +{ + struct iso_directory_record *dirp; + char *ptr; + size_t len, entrylen; + char namebuf[256]; + int i; + + while (*path && *path == '/') + path++; + + for (ptr = rootdirbuf, i = 1; + ptr < rootdirbuf + rootdirsize; + ptr += entrylen, i++) { + dirp = (struct iso_directory_record *)ptr; + entrylen = (u_char)dirp->length[0]; + len = (u_char)dirp->name_len[0]; + + DPRINTF(("# %d: offset 0x%x, length 0x%x = %d, ", + i, (int)(ptr - rootdirbuf), entrylen, entrylen)); + + if (entrylen == 0) { + DPRINTF(("EOD\n")); + break; + } + if (len == 0) { + DPRINTF(("name_len 0\n")); + continue; + } + if (len == 1 && + (dirp->name[0] == '\0' || dirp->name[1] == '\1')) { + DPRINTF(("dot/dot-dot entry\n")); + continue; + } + /* don't consider directories */ + if (dirp->flags[0] & 2) { + DPRINTF(("directory\n")); + continue; + } + +#ifdef DEBUG + bcopy(dirp->name, namebuf, len); + namebuf[len] = 0; + DPRINTF(("name `%s'\n", namebuf)); +#else /* !DEBUG */ + if (list_only) { + bcopy(dirp->name, namebuf, len); + namebuf[len] = 0; + printf("%s ", namebuf); + } +#endif /* DEBUG */ + + if (!list_only && + strncasecmp(path, dirp->name, len) == 0) + return dirp; + } +#ifndef DEBUG + if (list_only) + printf("\n"); +#endif + return 0; +} + +int +openrd(char *name) +{ + char *cp; + const char *fname; + u_int32_t oldsession; + int session, list_only; + struct iso_directory_record *dirp; + + session = 0; + fname = name; + + /* + * We accept the following boot string: + * + * [@sessionstart] name + */ + for (cp = name; *cp; cp++) + switch (*cp) { + /* we don't support filenames with spaces */ + case ' ': case '\t': + break; + + case '@': + if (session) { + printf("Syntax error\n"); + return -1; + } + session++; + oldsession = sessionstart; + sessionstart = 0; + break; + + case '0': case '1': case '2': + case '3': case '4': case '5': + case '6': case '7': case '8': + case '9': + if (session == 1) { + sessionstart *= 10; + sessionstart += *cp - '0'; + } + break; + + default: + if (session == 1) { + session++; + fname = cp; + } + } + + if (session && devopen(sessionstart) == -1) { + (void)devopen(oldsession); + sessionstart = oldsession; + } + if (session == 1) + /* XXX no filename, only session arg */ + return -1; + + list_only = fname[0] == '?' && fname[1] == 0; + + DPRINTF(("Calling find(%s, %d):\n", fname, list_only)); + dirp = find(fname, list_only); + DPRINTF(("find() returned 0x%x\n", (int)dirp)); + + if (list_only) + return -1; + if (dirp == 0) + return 1; + + startblk = isonum_733(dirp->extent); + filesize = isonum_733(dirp->size); + + DPRINTF(("startblk = %d, filesize = %d\n", startblk, filesize)); + + curblk = 0; /* force a re-read, 0 is impossible file start */ + seek(0); + + return 0; +} diff --git a/sys/i386/boot/cdboot/io.c b/sys/i386/boot/cdboot/io.c new file mode 100644 index 0000000..dc03262 --- /dev/null +++ b/sys/i386/boot/cdboot/io.c @@ -0,0 +1,287 @@ +/* + * 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, Revision 2.2 92/04/04 11:35:57 rpd + * $Id$ + */ + +#include "boot.h" +#include <machine/cpufunc.h> +#include <sys/reboot.h> + +#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ +#define K_STATUS 0x64 /* keyboard status */ +#define K_CMD 0x64 /* keybd ctlr command (write-only) */ + +#define K_OBUF_FUL 0x01 /* output buffer full */ +#define K_IBUF_FUL 0x02 /* input buffer full */ + +#define KC_CMD_WIN 0xd0 /* read output port */ +#define KC_CMD_WOUT 0xd1 /* write output port */ +#define KB_A20 0xdf /* enable A20, + enable output buffer full interrupt + enable data line + enable clock line */ + + +static int getchar(int in_buf); + +/* + * Gate A20 for high memory + */ +void +gateA20(void) +{ +#ifdef IBM_L40 + outb(0x92, 0x2); +#else /* IBM_L40 */ + while (inb(K_STATUS) & K_IBUF_FUL); + while (inb(K_STATUS) & K_OBUF_FUL) + (void)inb(K_RDWR); + + outb(K_CMD, KC_CMD_WOUT); + while (inb(K_STATUS) & K_IBUF_FUL); + outb(K_RDWR, KB_A20); + while (inb(K_STATUS) & K_IBUF_FUL); +#endif /* IBM_L40 */ +} + +/* printf - only handles %d as decimal, %c as char, %s as string */ + +void +printf(const char *format, ...) +{ + int *dataptr = (int *)&format; + char c; + + dataptr++; + while ((c = *format++)) + if (c != '%') + putchar(c); + else + switch (c = *format++) { + case 'd': { + int num = *dataptr++; + char buf[10], *ptr = buf; + if (num<0) { + num = -num; + putchar('-'); + } + do + *ptr++ = '0'+num%10; + while (num /= 10); + do + putchar(*--ptr); + while (ptr != buf); + break; + } + case 'x': { + unsigned int num = *dataptr++, dig; + char buf[8], *ptr = buf; + do + *ptr++ = (dig=(num&0xf)) > 9? + 'a' + dig - 10 : + '0' + dig; + while (num >>= 4); + do + putchar(*--ptr); + while (ptr != buf); + break; + } + case 'c': putchar((*dataptr++)&0xff); break; + case 's': { + char *ptr = (char *)*dataptr++; + while ((c = *ptr++)) + putchar(c); + break; + } + } +} + +void +putchar(int c) +{ + if (c == '\n') { + if (loadflags & RB_SERIAL) + serial_putc('\r'); + else + putc('\r'); + } + if (loadflags & RB_SERIAL) + serial_putc(c); + else + putc(c); +} + +static int +getchar(int in_buf) +{ + int c; + +loop: + if ((c = ((loadflags & RB_SERIAL) ? serial_getc() : getc())) == '\r') + c = '\n'; + if (c == '\b') { + if (in_buf != 0) { + putchar('\b'); + putchar(' '); + } else { + goto loop; + } + } + putchar(c); + return(c); +} + +#ifdef PROBE_KEYBOARD +/* + * This routine uses an inb to an unused port, the time to execute that + * inb is approximately 1.25uS. This value is pretty constant across + * all CPU's and all buses, with the exception of some PCI implentations + * that do not forward this I/O adress to the ISA bus as they know it + * is not a valid ISA bus address, those machines execute this inb in + * 60 nS :-(. + * + * XXX this should be converted to use bios_tick. + */ +void +delay1ms(void) +{ + int i = 800; + while (--i >= 0) + (void)inb(0x84); +} +#endif /* PROBE_KEYBOARD */ + +static __inline int +isch(void) +{ + int isc; + + /* + * Checking the keyboard has the side effect of enabling clock + * interrupts so that bios_tick works. Check the keyboard to + * get this side effect even if we only want the serial status. + */ + isc = ischar(); + + if (!(loadflags & RB_SERIAL)) + return (isc); + return (serial_ischar()); + +} + +static __inline unsigned +pword(unsigned physaddr) +{ + unsigned result; + + /* + * Give the fs prefix separately because gas omits it for + * "movl %fs:0x46c, %eax". + */ + __asm __volatile("fs; movl %1, %0" : "=r" (result) + : "m" (*(unsigned *)physaddr)); + return (result); +} + +int +gets(char *buf) +{ +#define bios_tick pword(0x46c) +#define BIOS_TICK_MS 55 + unsigned initial_bios_tick; + char *ptr=buf; + +#if BOOTWAIT + for (initial_bios_tick = bios_tick; + bios_tick - initial_bios_tick < BOOTWAIT / BIOS_TICK_MS;) +#endif + if (isch()) + for (;;) { + switch(*ptr = getchar(ptr - buf) & 0xff) { + case '\n': + case '\r': + *ptr = '\0'; + return 1; + case '\b': + if (ptr > buf) ptr--; + continue; + default: + ptr++; + } +#if TIMEOUT + 0 +#if !BOOTWAIT +#error "TIMEOUT without BOOTWAIT" +#endif + for (initial_bios_tick = bios_tick;;) { + if (isch()) + break; + if (bios_tick - initial_bios_tick >= + TIMEOUT / BIOS_TICK_MS) + return 0; + } +#endif + } + return 0; +} + +int +strncasecmp(const char *s1, const char *s2, size_t s) +{ + /* + * We only consider ASCII chars and don't anticipate + * control characters (they are invalid in filenames + * anyway). + */ + while (s > 0 && (*s1 & 0x5f) == (*s2 & 0x5f)) { + if (!*s1++) + return 0; + s2++; + } + if (s == 0) + return 0; + return 1; +} + +void +bcopy(const void *from, void *to, size_t len) +{ + char *fp = (char *)from; + char *tp = (char *)to; + + while (len-- > 0) + *tp++ = *fp++; +} + +/* To quote Ken: "You are not expected to understand this." :) */ + +void +twiddle(void) +{ + putchar((char)tw_chars); + tw_chars = (tw_chars >> 8) | ((tw_chars & (unsigned long)0xFF) << 24); + putchar('\b'); +} diff --git a/sys/i386/boot/cdboot/malloc.c b/sys/i386/boot/cdboot/malloc.c new file mode 100644 index 0000000..2b8486d --- /dev/null +++ b/sys/i386/boot/cdboot/malloc.c @@ -0,0 +1,179 @@ +/* + * Copyright © 1997 Pluto Technologies International, Inc. Boulder CO + * Copyright © 1997 interface business GmbH, Dresden. + * All rights reserved. + * + * This code was written by Jörg Wunsch, Dresden. + * Direct comments to <joerg_wunsch@interface-business.de>. + * + * 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(S) ``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(S) 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. + * + * $Id$ + */ + +/* + * Simple memory allocator for the bootstrap loader. Probably suffers + * a lot from fragmentation. + */ + +#include "boot.h" + +#include <stddef.h> + +/* ``Nobody will ever need more than 640 KB of RAM.'' :-) */ +#define MAXBRK (640 * 1024 * 1024) + +/* allocation unit */ +#define NCHUNKS 2048 + +struct chunk +{ + struct chunk *next; + size_t len; +}; + +static void *brkval; +static struct chunk *freelist; + +void * +malloc(size_t len) +{ + struct chunk *p, *q, *oldp; + size_t nelems; + + nelems = (len + sizeof(struct chunk) - 1) / sizeof(struct chunk) + 1; + + /* + * First, see if we can satisfy the request from the freelist. + */ + for (p = freelist, oldp = 0; + p && p != (struct chunk *)brkval; + oldp = p, p = p->next) { + if (p->len > nelems) { + /* chunk is larger, shorten, and return the tail */ + p->len -= nelems; + q = p + p->len; + q->next = 0; + q->len = nelems; + q++; + return (void *)q; + } + if (p->len == nelems) { + /* exact match, remove from freelist */ + if (oldp == 0) + freelist = p->next; + else + oldp->next = p->next; + p->next = 0; + p++; + return (void *)p; + } + } + /* + * Nothing found on freelist, try obtaining more space. + */ + if (brkval == 0) + brkval = &end; + q = p = (struct chunk *)brkval; + if ((int)(p + NCHUNKS) > MAXBRK) + return 0; + + p += NCHUNKS; + brkval = p; + + q->next = p; + q->len = NCHUNKS; + + if (oldp == 0) + freelist = q; + else { + if (oldp + oldp->len == q) { + /* extend last chunk */ + oldp->len += NCHUNKS; + oldp->next = p; + } else + oldp->next = q; + } + + return malloc(len); +} + +void +free(void *ptr) +{ + struct chunk *p, *q, *oldp; + + if (ptr == 0) + return; + + q = (struct chunk *)ptr; + q--; + if (q->next != 0) { + printf("malloc error: botched ptr to free()\n"); + return; + } + + /* + * Walk the freelist, and insert in the correct sequence. + */ + for (p = freelist, oldp = 0; + p && p != (struct chunk *)brkval; + oldp = p, p = p->next) { + if ((unsigned)p > (unsigned)q) { + if (q + q->len == p) { + /* aggregate with next chunk */ + q->len += p->len; + q->next = p->next; + p = p->next; + } + if (oldp) { + if (oldp + oldp->len == q) { + /* aggregate with previous chunk */ + oldp->len += q->len; + oldp->next = p; + } else { + /* insert into chain */ + q->next = p; + oldp->next = q; + } + return; + } + q->next = p; + freelist = q; + } + } + if (oldp) { + /* we are topmost */ + if (oldp + oldp->len == q) { + /* aggregate with previous chunk */ + oldp->len += q->len; + oldp->next = p; + } else { + oldp->next = q; + q->next = p; + } + return; + } + /* we are alone on the freelist */ + freelist = q; +} + |