147471Srnordier#
247471Srnordier# Copyright (c) 1999 Robert Nordier
347471Srnordier# All rights reserved.
447471Srnordier#
547471Srnordier# Redistribution and use in source and binary forms are freely
647471Srnordier# permitted provided that the above copyright notice and this
747471Srnordier# paragraph and the following disclaimer are duplicated in all
847471Srnordier# such forms.
947471Srnordier#
1047471Srnordier# This software is provided "AS IS" and without any express or
1147471Srnordier# implied warranties, including, without limitation, the implied
1247471Srnordier# warranties of merchantability and fitness for a particular
1347471Srnordier# purpose.
1447471Srnordier#
1547471Srnordier
1650477Speter# $FreeBSD: releng/10.3/sys/boot/i386/mbr/mbr.s 134431 2004-08-28 08:39:35Z yar $
1747471Srnordier
1862146Sjhb# A 512 byte MBR boot manager that simply boots the active partition.
1947471Srnordier
2047471Srnordier		.set LOAD,0x7c00		# Load address
2147471Srnordier		.set EXEC,0x600 		# Execution address
2247471Srnordier		.set PT_OFF,0x1be		# Partition table
2347471Srnordier		.set MAGIC,0xaa55		# Magic: bootable
24134431Syar		.set FL_PACKET,0x80		# Flag: try EDD
2547471Srnordier
2662176Sjhb		.set NHRDRV,0x475		# Number of hard drives
2747471Srnordier
2847471Srnordier		.globl start			# Entry point
2960822Sjhb		.code16
3047471Srnordier
3162146Sjhb#
3262146Sjhb# Setup the segment registers for flat addressing and setup the stack.
3362146Sjhb#
3447471Srnordierstart:		cld				# String ops inc
3560822Sjhb		xorw %ax,%ax			# Zero
3660822Sjhb		movw %ax,%es			# Address
3760822Sjhb		movw %ax,%ds			#  data
3860822Sjhb		movw %ax,%ss			# Set up
3960822Sjhb		movw $LOAD,%sp			#  stack
4062146Sjhb#
4162146Sjhb# Relocate ourself to a lower address so that we are out of the way when
4262146Sjhb# we load in the bootstrap from the partition to boot.
4362146Sjhb#
4460822Sjhb		movw $main-EXEC+LOAD,%si	# Source
4560822Sjhb		movw $main,%di			# Destination
4660822Sjhb		movw $0x200-(main-start),%cx	# Byte count
4747471Srnordier		rep				# Relocate
4847471Srnordier		movsb				#  code
4962146Sjhb#
5062146Sjhb# Jump to the relocated code.
5162146Sjhb#
5260822Sjhb		jmp main-LOAD+EXEC		# To relocated code
5362146Sjhb#
5462146Sjhb# Scan the partition table looking for an active entry.  Note that %ch is
5562146Sjhb# zero from the repeated string instruction above.  We save the offset of
5662146Sjhb# the active partition in %si and scan the entire table to ensure that only
5762146Sjhb# one partition is marked active.
5862146Sjhb#
5960822Sjhbmain:		xorw %si,%si			# No active partition
6060822Sjhb		movw $partbl,%bx		# Partition table
6148033Srnordier		movb $0x4,%cl			# Number of entries
6260822Sjhbmain.1: 	cmpb %ch,(%bx)			# Null entry?
6347471Srnordier		je main.2			# Yes
6448033Srnordier		jg err_pt			# If 0x1..0x7f
6560822Sjhb		testw %si,%si	 		# Active already found?
6647471Srnordier		jnz err_pt			# Yes
6760822Sjhb		movw %bx,%si			# Point to active
6847471Srnordiermain.2: 	addb $0x10,%bl			# Till
6947471Srnordier		loop main.1			#  done
7060822Sjhb		testw %si,%si	 		# Active found?
7147471Srnordier		jnz main.3			# Yes
7247471Srnordier		int $0x18			# BIOS: Diskless boot
7362146Sjhb#
7462146Sjhb# Ok, we've found a possible active partition.  Check to see that the drive
7562176Sjhb# is a valid hard drive number.
7662146Sjhb#
7747471Srnordiermain.3: 	cmpb $0x80,%dl			# Drive valid?
7847471Srnordier		jb main.4			# No
7962176Sjhb		movb NHRDRV,%dh			# Calculate the highest
8062176Sjhb		addb $0x80,%dh			#  drive number available
8162176Sjhb		cmpb %dh,%dl			# Within range?
8247471Srnordier		jb main.5			# Yes
8362176Sjhbmain.4: 	movb (%si),%dl			# Load drive
8462146Sjhb#
8562146Sjhb# Ok, now that we have a valid drive and partition entry, load the CHS from
8662146Sjhb# the partition entry and read the sector from the disk.
8762146Sjhb#
8862176Sjhbmain.5:		movw %sp,%di			# Save stack pointer
8962176Sjhb		movb 0x1(%si),%dh		# Load head
9060822Sjhb		movw 0x2(%si),%cx		# Load cylinder:sector
9160822Sjhb		movw $LOAD,%bx			# Transfer buffer
92134431Syar		testb $FL_PACKET,flags		# Try EDD?
93134431Syar		jz main.7			# No.
9462176Sjhb		pushw %cx			# Save %cx
9562176Sjhb		pushw %bx			# Save %bx
9662176Sjhb		movw $0x55aa,%bx		# Magic
9762176Sjhb		movb $0x41,%ah			# BIOS:	EDD extensions
9862176Sjhb		int $0x13			#  present?
9962176Sjhb		jc main.6			# No.
10062176Sjhb		cmpw $0xaa55,%bx		# Magic ok?
10162176Sjhb		jne main.6			# No.
10262176Sjhb		testb $0x1,%cl			# Packet mode present?
10362176Sjhb		jz main.6			# No.
10462176Sjhb		popw %bx			# Restore %bx
10562176Sjhb		pushl $0x0			# Set the LBA
10662176Sjhb		pushl 0x8(%si)			#  address
10762176Sjhb		pushw %es			# Set the address of
10862176Sjhb		pushw %bx			#  the transfer buffer
10962176Sjhb		pushw $0x1			# Read 1 sector
11062176Sjhb		pushw $0x10			# Packet length
11162176Sjhb		movw %sp,%si			# Packer pointer
11262176Sjhb		movw $0x4200,%ax		# BIOS:	LBA Read from disk
11362176Sjhb		jmp main.8			# Skip the CHS setup
11462176Sjhbmain.6:		popw %bx			# Restore %bx
11562176Sjhb		popw %cx			# Restore %cx
11662176Sjhbmain.7:		movw $0x201,%ax			# BIOS: Read from disk
11762176Sjhbmain.8:		int $0x13			# Call the BIOS
11862176Sjhb		movw %di,%sp			# Restore stack
11947471Srnordier		jc err_rd			# If error
12062146Sjhb#
12162146Sjhb# Now that we've loaded the bootstrap, check for the 0xaa55 signature.  If it
12262146Sjhb# is present, execute the bootstrap we just loaded.
12362146Sjhb#
12460822Sjhb		cmpw $MAGIC,0x1fe(%bx)		# Bootable?
12547471Srnordier		jne err_os			# No
12660822Sjhb		jmp *%bx			# Invoke bootstrap
12762146Sjhb#
12862146Sjhb# Various error message entry points.
12962146Sjhb#
13060822Sjhberr_pt: 	movw $msg_pt,%si		# "Invalid partition
13147471Srnordier		jmp putstr			#  table"
13247471Srnordier
13360822Sjhberr_rd: 	movw $msg_rd,%si		# "Error loading
13447471Srnordier		jmp putstr			#  operating system"
13547471Srnordier
13660822Sjhberr_os: 	movw $msg_os,%si		# "Missing operating
13747471Srnordier		jmp putstr			#  system"
13862146Sjhb#
13962146Sjhb# Output an ASCIZ string to the console via the BIOS.
14062146Sjhb#
14160822Sjhbputstr.0:	movw $0x7,%bx	 		# Page:attribute
14247471Srnordier		movb $0xe,%ah			# BIOS: Display
14347471Srnordier		int $0x10			#  character
14447471Srnordierputstr: 	lodsb				# Get character
14547471Srnordier		testb %al,%al			# End of string?
14647471Srnordier		jnz putstr.0			# No
14747471Srnordierputstr.1:	jmp putstr.1			# Await reset
14847471Srnordier
14947471Srnordiermsg_pt: 	.asciz "Invalid partition table"
15047471Srnordiermsg_rd: 	.asciz "Error loading operating system"
15147471Srnordiermsg_os: 	.asciz "Missing operating system"
15247471Srnordier
153134431Syar		.org PT_OFF-1,0x90
154134431Syarflags:		.byte FLAGS			# Flags
15547471Srnordier
15647471Srnordierpartbl: 	.fill 0x10,0x4,0x0		# Partition table
15747471Srnordier		.word MAGIC			# Magic number
158