Remove old i386 mbr stuff (move to arch/i386/stand/mbr a while ago)
mbr.8 moved to src/share/man/man8/man8.i386
This commit is contained in:
parent
baad6947d6
commit
ae60f83e33
@ -1,8 +1,6 @@
|
||||
# $NetBSD: Makefile,v 1.17 2003/04/30 19:50:42 dsl Exp $
|
||||
|
||||
MAN= mbr.8
|
||||
MLINKS= mbr.8 bootselect.8
|
||||
# $NetBSD: Makefile,v 1.18 2003/07/16 11:11:49 dsl Exp $
|
||||
|
||||
NOMAN=
|
||||
BINDIR= /usr/mdec
|
||||
BINMODE=444
|
||||
|
||||
|
@ -1,121 +0,0 @@
|
||||
.\" $NetBSD: mbr.8,v 1.10 2003/05/01 10:43:14 wiz Exp $
|
||||
.Dd April 30, 2003
|
||||
.Dt MBR 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mbr ,
|
||||
.Nm bootselect
|
||||
.Nd Master Boot Record bootcode
|
||||
.Sh DESCRIPTION
|
||||
An IBM PC boots from a disk by loading its first sector and executing
|
||||
the code in it.
|
||||
For a hard disk, this first sector usually contains a table of
|
||||
partitions present on the disk.
|
||||
The first sector of a disk containing such
|
||||
a table is called the Master Boot Record (MBR).
|
||||
.Pp
|
||||
The code present in the MBR will typically examine the partition
|
||||
table, find the partition that is marked active, and boot from it.
|
||||
Booting from a partition simply means loading the first sector in
|
||||
that partition, and executing the code in it, as is done for the
|
||||
MBR itself.
|
||||
.Pp
|
||||
.Nx
|
||||
supplies three versions of the MBR bootcode:
|
||||
.Bl -tag -width Er
|
||||
.It Sy Normal boot code
|
||||
This version has the same functionality as that supplied by DOS/Windows and
|
||||
other operating systems: it picks the active partition and boots from it.
|
||||
Its advantage over other, older MBRs, is that it can detect and use
|
||||
extensions to the BIOS interface that will allow it to boot partitions
|
||||
that cross or start beyond the 8 Gigabyte boundary.
|
||||
.It Sy Bootselector
|
||||
The bootselecting MBR contains configurable code that will present
|
||||
the user with a simple menu, allowing a choice between partitions to
|
||||
boot from, and hard disks to boot from.
|
||||
The choices and default settings can be configured through
|
||||
.Xr fdisk 8 .
|
||||
.It Sy Extended Bootselector
|
||||
The Extended Bootselecting MBR additionally allows
|
||||
.Nx
|
||||
to be loaded from an Extended partition.
|
||||
It only supports systems whose BIOS supports the extensions to
|
||||
boot partitions beyond the 8 Gigabyte boundary.
|
||||
.El
|
||||
.Pp
|
||||
The rest of this manual page will discuss the bootselecting versions of
|
||||
the MBR.
|
||||
The configurable items of the bootselector are:
|
||||
.Bl -tag -width Er
|
||||
.It timeout
|
||||
The number of seconds that the bootcode will wait for the user to
|
||||
press a key, selecting a menu item.
|
||||
Must be in the range 0-3600, or \-1 when it will wait forever.
|
||||
.It default
|
||||
The default partition or disk to boot from, should the timeout
|
||||
expire.
|
||||
.El
|
||||
.Pp
|
||||
The bootselector will output a menu of the
|
||||
.Em bootmenu
|
||||
names for each partition (as configured by
|
||||
.Xr fdisk 8 ) .
|
||||
The user can then select the partition
|
||||
or drive to boot from via the keyboard.
|
||||
.Pp
|
||||
The numeric keys
|
||||
.Sy 1
|
||||
upwards will initiate a startup from the corresponding partition.
|
||||
.Pp
|
||||
Function keys
|
||||
.Sy F1
|
||||
through
|
||||
.Sy F8
|
||||
will boot from harddisks 0 through 7 (BIOS numbers 0x80 through 0x87).
|
||||
Booting from a drive is simply done by reading the MBR of that
|
||||
drive and executing it, so the bootcode present in the MBR of the
|
||||
chosen drive determines which partition (if any) will be booted in
|
||||
the end.
|
||||
.Pp
|
||||
The
|
||||
.Sy Enter
|
||||
key will cause the bootcode to find the active partition, and boot from it.
|
||||
If no key is pressed, the (configurable) default selection is picked.
|
||||
.Sh DIAGNOSTICS
|
||||
The following error are detected:
|
||||
.Bl -column Code "No active partition"
|
||||
.It Em Code Ta Em "Text message" Ta Em Explanation
|
||||
.It 1 Ta "No active partition" Ta
|
||||
The MBR has a partition table without an active partition.
|
||||
.It 2 Ta "Disk read error" Ta
|
||||
There was an error reading the bootsector for the partition or
|
||||
drive selected.
|
||||
.It 3 Ta "No operating system" Ta
|
||||
The bootsector was loaded successfully, but it was not valid (i.e.,
|
||||
the magic number check failed, or it contained no code).
|
||||
.It L Ta "Invalid CHS read" Ta
|
||||
The boot partition cannot be read using a CHS read and the system BIOS
|
||||
doesn't support LBA reads.
|
||||
.It ? Ta "" Ta
|
||||
Unknown key.
|
||||
.El
|
||||
.Pp
|
||||
The standard boot code will output the text message and stop.
|
||||
It may be necessary to reset to the system to continue.
|
||||
.Pp
|
||||
The bootselect code will output 'Error \*[Lt]code\*[Gt]' and await further input.
|
||||
.Sh SEE ALSO
|
||||
.Xr boot 8 ,
|
||||
.Xr disklabel 8 ,
|
||||
.Xr fdisk 8 ,
|
||||
.Xr installboot 8 ,
|
||||
.Xr mbrlabel 8
|
||||
.Sh BUGS
|
||||
The bootselect code has constraints because of the limited amount of
|
||||
space available.
|
||||
The only way to be absolutely sure that a bootselector will always
|
||||
fit on the disk when a partition table is used, is to make it small
|
||||
enough to fit into the first sector (512 bytes, 404 excluding
|
||||
the partition table and bootselect menu).
|
||||
.Pp
|
||||
The error messages are necessarily terse.
|
@ -1,317 +0,0 @@
|
||||
/* $NetBSD: mbr.S,v 1.7 2002/08/04 20:27:22 ross Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1998 Wolfgang Solfrank.
|
||||
* Copyright (C) 1998 TooLs GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by TooLs GmbH.
|
||||
* 4. The name of TooLs GmbH may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* i386 master boot code
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
#define addr32 .byte 0x67
|
||||
#define data32 .byte 0x66
|
||||
|
||||
#define BOOTADDR 0x7c00
|
||||
|
||||
/*
|
||||
* XXX should be in an include file
|
||||
*/
|
||||
/*
|
||||
* Register values used in the i386 instruction set
|
||||
*/
|
||||
#define AL 0
|
||||
#define BL 3
|
||||
#define CL 1
|
||||
#define DL 2
|
||||
#define AH 4
|
||||
#define BH 7
|
||||
#define CH 5
|
||||
#define DH 6
|
||||
|
||||
#define AX 0
|
||||
#define BX 3
|
||||
#define CX 1
|
||||
#define DX 2
|
||||
#define SP 4
|
||||
#define BP 5
|
||||
#define SI 6
|
||||
#define DI 7
|
||||
|
||||
#define SI_INDEX 4
|
||||
#define DI_INDEX 5
|
||||
#define BP_INDEX 6
|
||||
#define BX_INDEX 7
|
||||
|
||||
#define cmpw_reg_iregoff(reg,ireg,off) \
|
||||
.byte 0x39 ; .byte (0x40 + ireg) | (reg << 3) ; .byte off
|
||||
|
||||
#define movb_ireg0_reg(ireg,reg) .byte 0x8a ; .byte (reg << 3) | ireg
|
||||
|
||||
#define movb_reg_mem(reg,mem) \
|
||||
.byte 0x88 ; .byte 0x6 | (reg << 3) ; .word mem
|
||||
#define movb_mem_reg(mem,reg) \
|
||||
.byte 0x8a ; .byte 0x6 | (reg << 3) ; .word mem
|
||||
|
||||
#define MINDRV 0x80
|
||||
#define MAXDRV 0x87
|
||||
|
||||
.text
|
||||
/*
|
||||
* Move ourselves out of the way first
|
||||
*/
|
||||
ENTRY(start)
|
||||
xorl %eax, %eax
|
||||
movl %eax, %ss
|
||||
data32
|
||||
movl $BOOTADDR, %esp
|
||||
movl %eax, %es
|
||||
movl %eax, %ds
|
||||
movl %esp, %esi
|
||||
data32
|
||||
movl $_C_LABEL(start), %edi
|
||||
data32
|
||||
movl $0x100, %ecx
|
||||
rep
|
||||
movsl
|
||||
#ifdef ASSEMBLE_16BIT
|
||||
jmp 0:1f
|
||||
#else
|
||||
.byte 0xea
|
||||
.word 1f
|
||||
.word 0
|
||||
#endif
|
||||
1:
|
||||
cmpb $MINDRV,%dl
|
||||
jl 2f
|
||||
cmpb $MAXDRV,%dl
|
||||
jle 3f
|
||||
2:
|
||||
movb $0x80,%dl
|
||||
3:
|
||||
movb_reg_mem(DL,drvno)
|
||||
/*
|
||||
* Now look for the active partition
|
||||
*/
|
||||
data32
|
||||
movl $parttab, %edi
|
||||
xorl %esi, %esi
|
||||
data32
|
||||
movl $4, %ecx
|
||||
1:
|
||||
addr32
|
||||
cmpb $0x80,0(%edi)
|
||||
jnz 2f
|
||||
test %esi, %esi
|
||||
jnz invpart
|
||||
data32
|
||||
movl %edi, %esi
|
||||
2:
|
||||
add $0x10, %edi
|
||||
loop 1b
|
||||
test %esi, %esi
|
||||
jnz boot
|
||||
/*
|
||||
* No active partition, or more than one partition active
|
||||
*/
|
||||
invpart:
|
||||
data32
|
||||
movl $msinvp, %esi
|
||||
jmp out
|
||||
|
||||
/*
|
||||
* Active partition pointed to by si.
|
||||
* Read the first sector.
|
||||
*
|
||||
* First:
|
||||
* - see what the total number of sectors is that we can address through the
|
||||
* normal CHS interface
|
||||
* - if this partition needs more, determine whether we have int13-extensions.
|
||||
*
|
||||
* Why this extra check? Well, some BIOSes apparently report that they do
|
||||
* int13 extensions, but fail if you actually use them (oh, great). So we
|
||||
* try to avoid them unless really necessary.
|
||||
*/
|
||||
boot:
|
||||
movb_mem_reg(drvno, DL);
|
||||
data32
|
||||
xorl %ecx,%ecx
|
||||
data32
|
||||
xorl %eax,%eax
|
||||
movb $8,%ah
|
||||
int $0x13
|
||||
|
||||
shrl $8,%edx
|
||||
incl %edx /* dx now has #heads */
|
||||
|
||||
movl %ecx,%eax
|
||||
andl $0x3f,%eax /* ax has #sectors */
|
||||
|
||||
movl %ecx,%ebx
|
||||
shrl $8,%ecx
|
||||
andl $0xc0,%ebx
|
||||
shll $2,%ebx
|
||||
orl %ebx,%ecx
|
||||
incl %ecx /* cx has #cylinders */
|
||||
|
||||
mull %edx /* h * s (will fit in 16 bits) */
|
||||
data32
|
||||
mull %ecx /* %eax = c * h * s */
|
||||
|
||||
movb_mem_reg(drvno, DL)
|
||||
|
||||
data32
|
||||
addr32
|
||||
movl 8(%esi), %ebx
|
||||
data32
|
||||
cmpl %eax, %ebx
|
||||
data32
|
||||
jl noext /* total # chs sectors > part. start */
|
||||
|
||||
tryext:
|
||||
data32
|
||||
push %esi
|
||||
push %edx
|
||||
data32
|
||||
movl $0x55aa, %ebx
|
||||
movb $0x41, %ah
|
||||
int $0x13
|
||||
pop %edx
|
||||
data32
|
||||
pop %esi
|
||||
jc noext
|
||||
data32
|
||||
movl $0xaa55,%eax
|
||||
cmpl %eax, %ebx
|
||||
jnz noext
|
||||
testb $1, %cl
|
||||
jz noext
|
||||
|
||||
/*
|
||||
* Modify the partition table entry to look like an int13-extension
|
||||
* parameter block.
|
||||
*/
|
||||
addr32
|
||||
data32
|
||||
movl $0x10010, 0(%esi)
|
||||
addr32
|
||||
data32
|
||||
movl $BOOTADDR, 4(%esi)
|
||||
addr32
|
||||
data32
|
||||
movl $0, 12(%esi)
|
||||
movb $5, %dh
|
||||
1:
|
||||
push %esi
|
||||
push %edx
|
||||
movb $0x42, %ah
|
||||
int $0x13
|
||||
pop %edx
|
||||
pop %esi
|
||||
jnc ok
|
||||
dec %dh
|
||||
jnz 1b
|
||||
rderr:
|
||||
data32
|
||||
movl $readerr, %esi
|
||||
out:
|
||||
lodsb
|
||||
testb %al, %al
|
||||
jz 1f
|
||||
movb $0xe, %ah
|
||||
movb $7, %bl
|
||||
push %esi
|
||||
int $0x10
|
||||
pop %esi
|
||||
jmp out
|
||||
1:
|
||||
sti
|
||||
jmp 1b
|
||||
|
||||
/*
|
||||
* No int13-extensions available, try old method.
|
||||
*/
|
||||
noext:
|
||||
addr32
|
||||
movb 1(%esi), %dh
|
||||
addr32
|
||||
movl 2(%esi), %ecx
|
||||
data32
|
||||
movl $5, %edi
|
||||
1:
|
||||
data32
|
||||
movl $BOOTADDR, %ebx
|
||||
data32
|
||||
movl $0x201, %eax
|
||||
push %edi
|
||||
push %edx
|
||||
push %ecx
|
||||
int $0x13
|
||||
pop %ecx
|
||||
pop %edx
|
||||
pop %edi
|
||||
jnc ok
|
||||
dec %edi
|
||||
jnz 1b
|
||||
jmp rderr
|
||||
|
||||
/*
|
||||
* Check signature for valid bootcode
|
||||
*/
|
||||
ok:
|
||||
data32
|
||||
mov $noos, %esi
|
||||
addr32
|
||||
movl BOOTADDR+0x1fe, %eax
|
||||
data32
|
||||
movl $0xaa55, %ebx
|
||||
cmpl %eax, %ebx
|
||||
jnz out
|
||||
movb_mem_reg(drvno, DL)
|
||||
#ifdef ASSEMBLE_16BIT
|
||||
jmp 0:BOOTADDR
|
||||
#else
|
||||
.byte 0xea
|
||||
.word BOOTADDR
|
||||
.word 0
|
||||
#endif
|
||||
|
||||
drvno:
|
||||
.byte 0x80
|
||||
msinvp:
|
||||
.asciz "Invalid partition table"
|
||||
noos:
|
||||
.asciz "No operating system"
|
||||
readerr:
|
||||
.asciz "Error loading operating system"
|
||||
. = _C_LABEL(start) + 0x1be
|
||||
parttab:
|
||||
. = _C_LABEL(start) + 0x1fe
|
||||
.byte 0x55, 0xaa
|
@ -1,32 +0,0 @@
|
||||
# $NetBSD: Makefile,v 1.12 2003/04/26 19:19:29 fvdl Exp $
|
||||
|
||||
NOMAN= # defined
|
||||
STRIPFLAG=
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
BINDIR= /usr/mdec
|
||||
BINMODE=444
|
||||
|
||||
PROG= mbr_bootsel
|
||||
SRCS= mbr_bootsel.S
|
||||
|
||||
.if ${OBJECT_FMT} == "ELF"
|
||||
LDFLAGS+= -e start
|
||||
.else
|
||||
LDFLAGS+= -e _start -N
|
||||
.endif
|
||||
|
||||
.if ${MACHINE} == "amd64"
|
||||
LDFLAGS+= -m elf_i386
|
||||
AFLAGS+= -m32
|
||||
.endif
|
||||
|
||||
|
||||
${PROG}: ${OBJS}
|
||||
${LD} -o ${PROG}.tmp ${LDFLAGS} -Ttext 0x600 ${OBJS}
|
||||
${STRIP} ${PROG}.tmp
|
||||
${OBJCOPY} -O binary ${PROG}.tmp ${PROG}
|
||||
rm -f ${PROG}.tmp
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,526 +0,0 @@
|
||||
/* $NetBSD: mbr_bootsel.S,v 1.6 2002/09/09 03:01:26 enami Exp $ */
|
||||
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Frank van der Linden.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the NetBSD
|
||||
* Foundation, Inc. and its contributors.
|
||||
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1998 Wolfgang Solfrank.
|
||||
* Copyright (C) 1998 TooLs GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by TooLs GmbH.
|
||||
* 4. The name of TooLs GmbH may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* i386 master boot code
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
#define data32 .byte 0x66
|
||||
|
||||
/*
|
||||
* Gas can't emit 16 bit code. Define each instruction that we need where
|
||||
* a 32-bit value (either data or addr) may be inserted in the generated
|
||||
* code, or where we would need a prefix but can do without (saving some
|
||||
* space).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Register values used in the i386 instruction set
|
||||
*/
|
||||
#define AL 0
|
||||
#define BL 3
|
||||
#define CL 1
|
||||
#define DL 2
|
||||
#define AH 4
|
||||
#define BH 7
|
||||
#define CH 5
|
||||
#define DH 6
|
||||
|
||||
#define AX 0
|
||||
#define BX 3
|
||||
#define CX 1
|
||||
#define DX 2
|
||||
#define SP 4
|
||||
#define BP 5
|
||||
#define SI 6
|
||||
#define DI 7
|
||||
|
||||
#define SI_INDEX 4
|
||||
#define DI_INDEX 5
|
||||
#define BP_INDEX 7
|
||||
|
||||
|
||||
/*
|
||||
* .. and the 16 bit instruction defines.
|
||||
*/
|
||||
#define call16(label) .byte 0xe8 ; .word label - . - 2
|
||||
#define jmp16(label) .byte 0xe9 ; .word label - . - 2
|
||||
#define jznear16(label) .byte 0x0f ; .byte 0x84 ; .word label - . - 2
|
||||
#define jmpfar(segval,addr) .byte 0xea ; .word addr ; .word segval
|
||||
|
||||
#define movb_mem_al(mem) .byte 0xa0 ; .word mem
|
||||
#define movb_al_mem(mem) .byte 0xa2 ; .word mem
|
||||
|
||||
#define movw_mem_ax(mem) .byte 0xa1 ; .word mem
|
||||
#define movw_ax_mem(mem) .byte 0xa3 ; .word mem
|
||||
|
||||
#define movw_mem_reg(mem,reg) \
|
||||
.byte 0x8b ; .byte (0x06 | ((reg) << 3)) ; .word mem
|
||||
|
||||
#define movw_imm_reg(imm,reg) \
|
||||
.byte 0xb8 | reg ; .word imm
|
||||
|
||||
#define movb_ireg0_reg(ireg,reg) .byte 0x8a ; .byte (reg << 3) | ireg
|
||||
#define movb_iregoff_reg(ireg,off,reg) \
|
||||
.byte 0x8a ; .byte 0x40 | (reg << 3) | ireg ; .byte off
|
||||
#define movw_iregoff_reg(ireg,off,reg) \
|
||||
.byte 0x8b ; .byte 0x40 | (reg << 3) | ireg ; .byte off
|
||||
|
||||
#define movb_reg_mem(reg,mem) \
|
||||
.byte 0x88 ; .byte 0x6 | (reg << 3) ; .word mem
|
||||
#define movb_mem_reg(mem,reg) \
|
||||
.byte 0x8a ; .byte 0x6 | (reg << 3) ; .word mem
|
||||
|
||||
#define movl_imm_ireg0(imm,ireg) \
|
||||
.byte 0x66 ; .byte 0xc7 ; .byte ireg ; .long imm
|
||||
#define movl_imm_iregoff(imm,ireg,off) \
|
||||
.byte 0x66 ; .byte 0xc7 ; .byte 0x40 | ireg ; .byte off ; .long imm
|
||||
|
||||
#define cmp_imm_ax(imm) .byte 0x3d ; .word imm
|
||||
|
||||
#define cmpb_imm_ireg0(imm,reg) \
|
||||
.byte 0x80 ; .byte 0x38 + reg ; .byte imm
|
||||
|
||||
#define cmpb_imm_iregoff(imm,reg,off) \
|
||||
.byte 0x80 ; .byte 0x78 + reg ; .byte off ; .byte imm
|
||||
|
||||
#define cmpb_imm_ireg0_bx(imm,reg) \
|
||||
.byte 0x80 ; .byte 0x34 + reg ; .byte imm
|
||||
|
||||
#define cmpb_mem_reg(mem,reg) .byte 0x3a ; .byte 0x06 | (reg << 3) ; .word mem
|
||||
#define cmpw_imm_reg(imm,reg) .byte 0x81 ; .byte 0xf8 + reg ; .word imm
|
||||
|
||||
#define and_imm_ax(imm) .byte 0x25 ; .word imm
|
||||
|
||||
|
||||
|
||||
#define BOOTADDR 0x7c00
|
||||
|
||||
/*
|
||||
* Each entry in the boot select table is a nul-terminated string
|
||||
* of 8 bytes (not including the 0). A zero-length string (i.e.
|
||||
* the first char is 0) indicates an unused entry.
|
||||
*/
|
||||
#define PARTNAMESIZE 8
|
||||
#define TABENTRYSIZE (PARTNAMESIZE + 1)
|
||||
#define NAMETABSIZE 4 * TABENTRYSIZE
|
||||
|
||||
/*
|
||||
* Flag defines. Currently only used to make the boot selector active
|
||||
* or inactive. There may never be more because of space constraints.
|
||||
*/
|
||||
#define BFL_SELACTIVE 0x01
|
||||
#define BFL_EXTINT13 0x02
|
||||
|
||||
/*
|
||||
* Scan values for the various keys we use, as returned by the BIOS
|
||||
*/
|
||||
#define SCAN_ENTER 0x1c
|
||||
#define SCAN_F1 0x3b
|
||||
#define SCAN_F5 0x3f
|
||||
#define SCAN_F10 0x44
|
||||
|
||||
/*
|
||||
* Minimum and maximum drive number that is considered to be valid.
|
||||
*/
|
||||
#define MINDRV 0x80
|
||||
#define MAXDRV 0x87
|
||||
|
||||
/*
|
||||
* Error codes. Done this way to save space.
|
||||
*/
|
||||
#define ERR_INVPART '1' /* Invalid partition table */
|
||||
#define ERR_READ '2' /* Read error */
|
||||
#define ERR_NOOS '3' /* Magic no. check failed for part. */
|
||||
|
||||
.text
|
||||
/*
|
||||
* Move ourselves out of the way first.
|
||||
*/
|
||||
ENTRY(start)
|
||||
data32
|
||||
xorl %eax, %eax
|
||||
movl %eax, %ss
|
||||
movl $BOOTADDR, %esp
|
||||
movl %eax, %es
|
||||
movl %eax, %ds
|
||||
xorl %esi,%esi
|
||||
movl %esp, %esi
|
||||
movw_imm_reg(_C_LABEL(start),DI)
|
||||
movw_imm_reg(0x100,CX)
|
||||
rep
|
||||
movsl
|
||||
jmpfar(0,1f)
|
||||
/*
|
||||
* Sanity check the drive number passed by the BIOS. Some BIOSs may not
|
||||
* do this and pass garbage.
|
||||
*/
|
||||
1:
|
||||
cmpb $MINDRV,%dl
|
||||
jl 2f
|
||||
cmpb $MAXDRV,%dl
|
||||
jle 3f
|
||||
2:
|
||||
movb $0x80,%dl
|
||||
3:
|
||||
movb_reg_mem(DL,drvno)
|
||||
bootsel:
|
||||
movb_mem_al(flags)
|
||||
testb $BFL_SELACTIVE,%al
|
||||
jznear16(getactive)
|
||||
/*
|
||||
* The bootselector is active. Walk through the selector (name) table,
|
||||
* printing used entries.
|
||||
*/
|
||||
movw_imm_reg(nametab,DI)
|
||||
movb $0x31,%al
|
||||
movb $4,%cl
|
||||
1:
|
||||
cmpb_imm_ireg0(0,DI_INDEX)
|
||||
jz 2f
|
||||
movb_al_mem(prefix+1)
|
||||
movw_imm_reg(prefix,SI)
|
||||
call16(putasciz)
|
||||
movl %edi,%esi
|
||||
call16(putasciz)
|
||||
movw_imm_reg(newline,SI);
|
||||
call16(putasciz)
|
||||
2:
|
||||
incb %al
|
||||
addl $TABENTRYSIZE,%edi
|
||||
loop 1b
|
||||
|
||||
/*
|
||||
* Get the initial time value for the timeout comparison. It is returned
|
||||
* by int 1a in cx:dx. Make sure to grab the whole 32 bit value, otherwise
|
||||
* it'd wrap around every hour. Now it'll only do so every 24 hours. Boots
|
||||
* should happen infrequent enough that this isn't a problem.
|
||||
*
|
||||
* Loop around checking for a keypress until we have one, or timeout is
|
||||
* reached.
|
||||
*/
|
||||
xorb %ah,%ah
|
||||
int $0x1a
|
||||
data32
|
||||
shll $16,%ecx
|
||||
movl %edx,%edi
|
||||
data32
|
||||
orl %ecx,%edi
|
||||
3:
|
||||
movb $1,%ah
|
||||
int $0x16
|
||||
jnz 4f
|
||||
xorb %ah,%ah
|
||||
int $0x1a
|
||||
data32
|
||||
shll $16,%ecx
|
||||
data32
|
||||
orl %ecx,%edx
|
||||
data32
|
||||
subl %edi,%edx
|
||||
movw_mem_ax(timeout)
|
||||
cmpl %eax,%edx
|
||||
jl 3b
|
||||
movb_mem_al(defkey)
|
||||
jmp default
|
||||
4:
|
||||
xorb %ah,%ah
|
||||
int $0x16
|
||||
movb %ah,%al
|
||||
default:
|
||||
/*
|
||||
* <enter> -> boot active partition.
|
||||
*/
|
||||
cmpb $SCAN_ENTER,%al
|
||||
je getactive
|
||||
/*
|
||||
* F1-F4 -> boot partition 1-4
|
||||
*/
|
||||
subb $SCAN_F1,%al
|
||||
cmpb $9,%al
|
||||
jg 4b
|
||||
cmpb $3,%al
|
||||
jle 5f
|
||||
/*
|
||||
* F5-F10 -> boot disk 0-5. Check if the requested disk isn't above
|
||||
* the number of disks actually in the system as stored in 0:0475 by
|
||||
* the BIOS. This is always sector 0, so never use int13 extensions.
|
||||
*/
|
||||
subb $4,%al
|
||||
cmpb_mem_reg(0x0475,AL)
|
||||
jge 4b
|
||||
movw_imm_reg(fakeent,SI)
|
||||
addb $0x80,%al
|
||||
movb %al,%dl
|
||||
jmp16(noext)
|
||||
5:
|
||||
/*
|
||||
* Check if the requested entry is actually active in the partition and
|
||||
* bootmenu table. If not, just do nothing.
|
||||
*/
|
||||
movw_imm_reg(parttab,SI)
|
||||
and_imm_ax(0xff)
|
||||
movl %eax,%ebx
|
||||
shll $4,%eax
|
||||
add %eax,%esi
|
||||
cmpb_imm_iregoff(0,SI_INDEX,4)
|
||||
je 4b
|
||||
movw_imm_reg(nametab,DI)
|
||||
imul $TABENTRYSIZE,%ebx
|
||||
cmpb_imm_ireg0_bx(0,DI_INDEX)
|
||||
je 4b
|
||||
jmp boot
|
||||
|
||||
/*
|
||||
* Look for the (first) active partition
|
||||
*/
|
||||
getactive:
|
||||
movw_imm_reg(parttab,SI)
|
||||
movw_imm_reg(4,CX)
|
||||
1:
|
||||
cmpb_imm_ireg0(0x80,SI_INDEX)
|
||||
jz boot
|
||||
addl $0x10, %esi
|
||||
loop 1b
|
||||
/*
|
||||
* No active partition.
|
||||
*/
|
||||
invpart:
|
||||
movb $ERR_INVPART,%al
|
||||
jmp errhang
|
||||
|
||||
/*
|
||||
* Active partition pointed to by si.
|
||||
* Read the first sector.
|
||||
*
|
||||
* First determine whether we have int13-extensions, by calling
|
||||
* int 13, function 41. Check for the magic number returned,
|
||||
* and the disk packet capability.
|
||||
*/
|
||||
boot:
|
||||
movb_mem_reg(drvno,DL)
|
||||
boot2:
|
||||
movb_mem_al(flags)
|
||||
testb $BFL_EXTINT13,%al
|
||||
jz noext
|
||||
|
||||
push %esi
|
||||
push %edx
|
||||
movw_imm_reg(0x55aa,BX)
|
||||
movb $0x41, %ah
|
||||
int $0x13
|
||||
pop %edx
|
||||
pop %esi
|
||||
jc noext
|
||||
cmpw_imm_reg(0xaa55,BX)
|
||||
jnz noext
|
||||
testb $1, %cl
|
||||
jz noext
|
||||
|
||||
/*
|
||||
* Modify the partition table entry to look like an int13-extension
|
||||
* parameter block, so we can feed it to the extended read call.
|
||||
* XXX this means that we can only use it once, we can't jump back
|
||||
* here if the read fails.
|
||||
*/
|
||||
movl_imm_ireg0(0x10010,SI_INDEX)
|
||||
movl_imm_iregoff(BOOTADDR,SI_INDEX,4)
|
||||
movl_imm_iregoff(0,SI_INDEX,12)
|
||||
movb $5, %dh
|
||||
1:
|
||||
push %esi
|
||||
push %edx
|
||||
movb $0x42, %ah
|
||||
int $0x13
|
||||
pop %edx
|
||||
pop %esi
|
||||
jnc ok
|
||||
dec %dh
|
||||
jnz 1b
|
||||
rderr:
|
||||
movb $ERR_READ,%al
|
||||
errhang:
|
||||
call16(putc)
|
||||
hang:
|
||||
sti
|
||||
jmp hang
|
||||
/*
|
||||
* print a 0-terminated ASCII string. Address in si.
|
||||
*/
|
||||
putasciz:
|
||||
push %eax
|
||||
1:
|
||||
lodsb
|
||||
testb %al, %al
|
||||
jz 2f
|
||||
call16(putc)
|
||||
jmp 1b
|
||||
2:
|
||||
pop %eax
|
||||
ret
|
||||
putc:
|
||||
movb $0xe, %ah
|
||||
movb $7, %bl
|
||||
int $0x10
|
||||
ret
|
||||
|
||||
/*
|
||||
* No int13-extensions available, try old the method to load the frirst
|
||||
* sector of the partition.
|
||||
*/
|
||||
noext:
|
||||
movb_iregoff_reg(SI_INDEX,1,DH)
|
||||
movw_iregoff_reg(SI_INDEX,2,CX)
|
||||
load:
|
||||
movw_imm_reg(5,DI)
|
||||
1:
|
||||
movw_imm_reg(BOOTADDR,BX)
|
||||
movw_imm_reg(0x201,AX)
|
||||
push %edi
|
||||
push %edx
|
||||
int $0x13
|
||||
pop %edx
|
||||
pop %edi
|
||||
jnc ok
|
||||
dec %edi
|
||||
jnz 1b
|
||||
jmp rderr
|
||||
|
||||
/*
|
||||
* Check signature for valid bootcode
|
||||
*/
|
||||
ok:
|
||||
movw_mem_ax(BOOTADDR+0x1fe)
|
||||
cmp_imm_ax(0xaa55)
|
||||
jz 1f
|
||||
movb $ERR_NOOS,%al
|
||||
jmp errhang
|
||||
1:
|
||||
jmpfar(0,BOOTADDR)
|
||||
|
||||
newline:
|
||||
.asciz "\r\n"
|
||||
prefix:
|
||||
.asciz "F1: "
|
||||
/*
|
||||
* Fake partition entry used to boot from other disks. First byte is
|
||||
* overloaded, it's also used as storage for the drive number. We're
|
||||
* not using that in the entry.
|
||||
*/
|
||||
drvno:
|
||||
fakeent:
|
||||
.byte 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00
|
||||
.long 0x0000, 0x0001
|
||||
. = _C_LABEL(start) + (0x1bc - NAMETABSIZE - 4)
|
||||
/*
|
||||
* Default action, as a keyvalue we'd normally read from the BIOS. This
|
||||
* saves a bit of space.
|
||||
*/
|
||||
defkey:
|
||||
.byte SCAN_ENTER
|
||||
flags:
|
||||
.byte 0x01
|
||||
/*
|
||||
* Timeout value. 65536 ticks per hour, which is about 18.2 times per second.
|
||||
*/
|
||||
timeout:
|
||||
.word 0x00b6
|
||||
/*
|
||||
* Space for name/select table and partition table. If DEBUG is defined,
|
||||
* use some values from one of my machines, for testing.
|
||||
*/
|
||||
nametab:
|
||||
#ifdef DEBUG
|
||||
.asciz "Windows "
|
||||
.asciz "NetBSD "
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
#else
|
||||
.fill NAMETABSIZE,0x01,0x00
|
||||
#endif
|
||||
. = _C_LABEL(start) + 0x1bc
|
||||
ourmagic:
|
||||
.byte 0x55, 0xaa
|
||||
. = _C_LABEL(start) + 0x1be
|
||||
#ifdef DEBUG
|
||||
parttab:
|
||||
.word 0x0100
|
||||
.word 0x0001, 0xde06, 0x1f3e, 0x003f, 0x0000, 0xd000, 0x0007, 0xde80
|
||||
.word 0x1f3f, 0x24a5, 0xe57e, 0xd03f, 0x0007, 0x1c80, 0x006f, 0x0000
|
||||
.word 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
.word 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
|
||||
#else
|
||||
parttab:
|
||||
.fill 0x40,0x01,0x00
|
||||
#endif
|
||||
. = _C_LABEL(start) + 0x1fe
|
||||
.byte 0x55, 0xaa
|
Loading…
x
Reference in New Issue
Block a user