(Part #2, after the Internet link broke totally yesterday.)
This is the long-threatened ISO 9660 CD-ROM bootstrap code. This work has been sponsored by Plutotech International, Inc (who paid the initial work), and interface business GmbH (where i did most of the work). A big thanks also goes to Bruce Evans, for his continuing help and answering my stupid questions. The code is basically functioning, with the following caveats: . Rock Ridge attributes are not yet supported. . Only SCSI CD-ROMs are supported, since i fail to see any possibility to determine the drive type using BIOS functions. (Even for hard disks, this determination is done by a big hack only.) . El Torito specifies a lot of crap and useless misfeatures, but crucial things like the ability to figure out the CD TOC have been ``forgotten''. Thus, if you wanna boot a multisession CD, you need to know at which CD block your session starts, and need to speciffy it using the @ clause. . None of the CD-ROM controllers i've seen so far implements the full El Torito specification at all. Adaptec is probably the closest, but they miss on non-emulation booting (which would be the most logical choice for us). Thus, the current code bloats the 7.5 KB boot code up to 1.44 MB, in order to fake a `floppy' image. If you wanna use it, specify this file as the boot image on the command-line of the mksiosfs command (option -b). Caveat emptor: some versions of the Adaptec BIOS might even fail to access the CD-ROM at all, using the BIOS functions. I think i've notice this for ver 1.26, the code has been tested with ver 1.23. The boot string is as follows: [@sess-start] [filename] [-flags] sess-start Extend # where the last session starts, measured in CD-ROM blocks. filename As usual, but the input is case-insensitive by now (since we don't grok RR anyway). flags As usual, but -C (use CDROM root f/s) is default, so specifying -C will decactivate this option (which is probably not what you want :). A lot of cleanup work is probably required, and some of the files could/should be merged back to biosboot, perhaps made conditional on some #ifdef. The malloc implementation that comes with cdboot might also be useful for kzipboot. (I needed a malloc() since the root dir ain't fixed in size on a CD.) I've been testing all this with a 2.2-STABLE as the base for biosboot. I don't expect too many surprises, although i know the biosboot stuff has been changed a lot in -current lately. I'm sure Bruce will comment on all this here anyway. :-)
This commit is contained in:
parent
b55cfe9f16
commit
c81672091f
114
sys/i386/boot/cdboot/Makefile
Normal file
114
sys/i386/boot/cdboot/Makefile
Normal file
@ -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>
|
278
sys/i386/boot/cdboot/asm.S
Normal file
278
sys/i386/boot/cdboot/asm.S
Normal file
@ -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
|
411
sys/i386/boot/cdboot/bios.S
Normal file
411
sys/i386/boot/cdboot/bios.S
Normal file
@ -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
|
393
sys/i386/boot/cdboot/boot.c
Normal file
393
sys/i386/boot/cdboot/boot.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
180
sys/i386/boot/cdboot/boot.h
Normal file
180
sys/i386/boot/cdboot/boot.h
Normal file
@ -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;
|
356
sys/i386/boot/cdboot/cdrom.c
Normal file
356
sys/i386/boot/cdboot/cdrom.c
Normal file
@ -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;
|
||||
}
|
287
sys/i386/boot/cdboot/io.c
Normal file
287
sys/i386/boot/cdboot/io.c
Normal file
@ -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');
|
||||
}
|
179
sys/i386/boot/cdboot/malloc.c
Normal file
179
sys/i386/boot/cdboot/malloc.c
Normal file
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user