freebsd-skq/sys/boot/i386/mbr/mbr.s
yar e8321616db Don't be too smart, just try packet mode of INT13 first.
This way of operation is more robust than the "AI" used
before.

Add flags to mbr accessible from make.conf as BOOT_MBR_FLAGS.
Only one flag is defined now, "allow using packet mode", which
is 0x80 in accord with the rest of i386 boot code.  The "packet"
flag is on by default.

PR:             i386/70241
Submitted by:   Valentin Nechayev <netch <@> netch.kiev.ua> (inital version)
Discussed with: jhb (by Valentin Nechayev)
Tested on:      bochs (with EDD turned on or off by patching the BIOS), PCs
2004-08-28 08:39:35 +00:00

158 lines
4.6 KiB
ArmAsm

#
# Copyright (c) 1999 Robert Nordier
# All rights reserved.
#
# Redistribution and use in source and binary forms are freely
# permitted provided that the above copyright notice and this
# paragraph and the following disclaimer are duplicated in all
# such forms.
#
# This software is provided "AS IS" and without any express or
# implied warranties, including, without limitation, the implied
# warranties of merchantability and fitness for a particular
# purpose.
#
# $FreeBSD$
# A 512 byte MBR boot manager that simply boots the active partition.
.set LOAD,0x7c00 # Load address
.set EXEC,0x600 # Execution address
.set PT_OFF,0x1be # Partition table
.set MAGIC,0xaa55 # Magic: bootable
.set FL_PACKET,0x80 # Flag: try EDD
.set NHRDRV,0x475 # Number of hard drives
.globl start # Entry point
.code16
#
# Setup the segment registers for flat addressing and setup the stack.
#
start: cld # String ops inc
xorw %ax,%ax # Zero
movw %ax,%es # Address
movw %ax,%ds # data
movw %ax,%ss # Set up
movw $LOAD,%sp # stack
#
# Relocate ourself to a lower address so that we are out of the way when
# we load in the bootstrap from the partition to boot.
#
movw $main-EXEC+LOAD,%si # Source
movw $main,%di # Destination
movw $0x200-(main-start),%cx # Byte count
rep # Relocate
movsb # code
#
# Jump to the relocated code.
#
jmp main-LOAD+EXEC # To relocated code
#
# Scan the partition table looking for an active entry. Note that %ch is
# zero from the repeated string instruction above. We save the offset of
# the active partition in %si and scan the entire table to ensure that only
# one partition is marked active.
#
main: xorw %si,%si # No active partition
movw $partbl,%bx # Partition table
movb $0x4,%cl # Number of entries
main.1: cmpb %ch,(%bx) # Null entry?
je main.2 # Yes
jg err_pt # If 0x1..0x7f
testw %si,%si # Active already found?
jnz err_pt # Yes
movw %bx,%si # Point to active
main.2: addb $0x10,%bl # Till
loop main.1 # done
testw %si,%si # Active found?
jnz main.3 # Yes
int $0x18 # BIOS: Diskless boot
#
# Ok, we've found a possible active partition. Check to see that the drive
# is a valid hard drive number.
#
main.3: cmpb $0x80,%dl # Drive valid?
jb main.4 # No
movb NHRDRV,%dh # Calculate the highest
addb $0x80,%dh # drive number available
cmpb %dh,%dl # Within range?
jb main.5 # Yes
main.4: movb (%si),%dl # Load drive
#
# Ok, now that we have a valid drive and partition entry, load the CHS from
# the partition entry and read the sector from the disk.
#
main.5: movw %sp,%di # Save stack pointer
movb 0x1(%si),%dh # Load head
movw 0x2(%si),%cx # Load cylinder:sector
movw $LOAD,%bx # Transfer buffer
testb $FL_PACKET,flags # Try EDD?
jz main.7 # No.
pushw %cx # Save %cx
pushw %bx # Save %bx
movw $0x55aa,%bx # Magic
movb $0x41,%ah # BIOS: EDD extensions
int $0x13 # present?
jc main.6 # No.
cmpw $0xaa55,%bx # Magic ok?
jne main.6 # No.
testb $0x1,%cl # Packet mode present?
jz main.6 # No.
popw %bx # Restore %bx
pushl $0x0 # Set the LBA
pushl 0x8(%si) # address
pushw %es # Set the address of
pushw %bx # the transfer buffer
pushw $0x1 # Read 1 sector
pushw $0x10 # Packet length
movw %sp,%si # Packer pointer
movw $0x4200,%ax # BIOS: LBA Read from disk
jmp main.8 # Skip the CHS setup
main.6: popw %bx # Restore %bx
popw %cx # Restore %cx
main.7: movw $0x201,%ax # BIOS: Read from disk
main.8: int $0x13 # Call the BIOS
movw %di,%sp # Restore stack
jc err_rd # If error
#
# Now that we've loaded the bootstrap, check for the 0xaa55 signature. If it
# is present, execute the bootstrap we just loaded.
#
cmpw $MAGIC,0x1fe(%bx) # Bootable?
jne err_os # No
jmp *%bx # Invoke bootstrap
#
# Various error message entry points.
#
err_pt: movw $msg_pt,%si # "Invalid partition
jmp putstr # table"
err_rd: movw $msg_rd,%si # "Error loading
jmp putstr # operating system"
err_os: movw $msg_os,%si # "Missing operating
jmp putstr # system"
#
# Output an ASCIZ string to the console via the BIOS.
#
putstr.0: movw $0x7,%bx # Page:attribute
movb $0xe,%ah # BIOS: Display
int $0x10 # character
putstr: lodsb # Get character
testb %al,%al # End of string?
jnz putstr.0 # No
putstr.1: jmp putstr.1 # Await reset
msg_pt: .asciz "Invalid partition table"
msg_rd: .asciz "Error loading operating system"
msg_os: .asciz "Missing operating system"
.org PT_OFF-1,0x90
flags: .byte FLAGS # Flags
partbl: .fill 0x10,0x4,0x0 # Partition table
.word MAGIC # Magic number