aboutsummaryrefslogtreecommitdiff
path: root/sys/boot/i386/mbr/mbr.s
blob: 3cfc20dd58e19d1cdbfeaf1a3896243e4250487d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#
# 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