318 lines
6.0 KiB
ArmAsm
318 lines
6.0 KiB
ArmAsm
/* $NetBSD: mbr.S,v 1.6 1999/05/02 13:48:30 fvdl 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 %ax, %ss
|
|
data32
|
|
movl $BOOTADDR, %esp
|
|
movl %ax, %es
|
|
movl %ax, %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
|