e8321616db
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
158 lines
4.6 KiB
ArmAsm
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
|