(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:
joerg 1997-07-11 05:52:41 +00:00
parent b55cfe9f16
commit c81672091f
8 changed files with 2198 additions and 0 deletions

View 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
View 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
View 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
View 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
View 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;

View 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
View 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');
}

View 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;
}