xref: /freebsd/stand/i386/mbr/mbr.S (revision f7eb23ee)
1f7eb23eeSEd Maste#
2f7eb23eeSEd Maste# Copyright (c) 1999 Robert Nordier
3f7eb23eeSEd Maste# All rights reserved.
4f7eb23eeSEd Maste#
5f7eb23eeSEd Maste# Redistribution and use in source and binary forms are freely
6f7eb23eeSEd Maste# permitted provided that the above copyright notice and this
7f7eb23eeSEd Maste# paragraph and the following disclaimer are duplicated in all
8f7eb23eeSEd Maste# such forms.
9f7eb23eeSEd Maste#
10f7eb23eeSEd Maste# This software is provided "AS IS" and without any express or
11f7eb23eeSEd Maste# implied warranties, including, without limitation, the implied
12f7eb23eeSEd Maste# warranties of merchantability and fitness for a particular
13f7eb23eeSEd Maste# purpose.
14f7eb23eeSEd Maste#
15f7eb23eeSEd Maste
16f7eb23eeSEd Maste# $FreeBSD$
17f7eb23eeSEd Maste
18f7eb23eeSEd Maste# A 512 byte MBR boot manager that simply boots the active partition.
19f7eb23eeSEd Maste
20f7eb23eeSEd Maste		.set LOAD,0x7c00		# Load address
21f7eb23eeSEd Maste		.set EXEC,0x600 		# Execution address
22f7eb23eeSEd Maste		.set PT_OFF,0x1be		# Partition table
23f7eb23eeSEd Maste		.set MAGIC,0xaa55		# Magic: bootable
24f7eb23eeSEd Maste		.set FL_PACKET,0x80		# Flag: try EDD
25f7eb23eeSEd Maste
26f7eb23eeSEd Maste		.set NHRDRV,0x475		# Number of hard drives
27f7eb23eeSEd Maste
28f7eb23eeSEd Maste		.globl start			# Entry point
29f7eb23eeSEd Maste		.code16
30f7eb23eeSEd Maste
31f7eb23eeSEd Maste#
32f7eb23eeSEd Maste# Setup the segment registers for flat addressing and setup the stack.
33f7eb23eeSEd Maste#
34f7eb23eeSEd Mastestart:		cld				# String ops inc
35f7eb23eeSEd Maste		xorw %ax,%ax			# Zero
36f7eb23eeSEd Maste		movw %ax,%es			# Address
37f7eb23eeSEd Maste		movw %ax,%ds			#  data
38f7eb23eeSEd Maste		movw %ax,%ss			# Set up
39f7eb23eeSEd Maste		movw $LOAD,%sp			#  stack
40f7eb23eeSEd Maste#
41f7eb23eeSEd Maste# Relocate ourself to a lower address so that we are out of the way when
42f7eb23eeSEd Maste# we load in the bootstrap from the partition to boot.
43f7eb23eeSEd Maste#
44f7eb23eeSEd Maste		movw $main-EXEC+LOAD,%si	# Source
45f7eb23eeSEd Maste		movw $main,%di			# Destination
46f7eb23eeSEd Maste		movw $0x200-(main-start),%cx	# Byte count
47f7eb23eeSEd Maste		rep				# Relocate
48f7eb23eeSEd Maste		movsb				#  code
49f7eb23eeSEd Maste#
50f7eb23eeSEd Maste# Jump to the relocated code.
51f7eb23eeSEd Maste#
52f7eb23eeSEd Maste		jmp main-LOAD+EXEC		# To relocated code
53f7eb23eeSEd Maste#
54f7eb23eeSEd Maste# Scan the partition table looking for an active entry.  Note that %ch is
55f7eb23eeSEd Maste# zero from the repeated string instruction above.  We save the offset of
56f7eb23eeSEd Maste# the active partition in %si and scan the entire table to ensure that only
57f7eb23eeSEd Maste# one partition is marked active.
58f7eb23eeSEd Maste#
59f7eb23eeSEd Mastemain:		xorw %si,%si			# No active partition
60f7eb23eeSEd Maste		movw $partbl,%bx		# Partition table
61f7eb23eeSEd Maste		movb $0x4,%cl			# Number of entries
62f7eb23eeSEd Mastemain.1: 	cmpb %ch,(%bx)			# Null entry?
63f7eb23eeSEd Maste		je main.2			# Yes
64f7eb23eeSEd Maste		jg err_pt			# If 0x1..0x7f
65f7eb23eeSEd Maste		testw %si,%si	 		# Active already found?
66f7eb23eeSEd Maste		jnz err_pt			# Yes
67f7eb23eeSEd Maste		movw %bx,%si			# Point to active
68f7eb23eeSEd Mastemain.2: 	addb $0x10,%bl			# Till
69f7eb23eeSEd Maste		loop main.1			#  done
70f7eb23eeSEd Maste		testw %si,%si	 		# Active found?
71f7eb23eeSEd Maste		jnz main.3			# Yes
72f7eb23eeSEd Maste		int $0x18			# BIOS: Diskless boot
73f7eb23eeSEd Maste#
74f7eb23eeSEd Maste# Ok, we've found a possible active partition.  Check to see that the drive
75f7eb23eeSEd Maste# is a valid hard drive number.
76f7eb23eeSEd Maste#
77f7eb23eeSEd Mastemain.3: 	cmpb $0x80,%dl			# Drive valid?
78f7eb23eeSEd Maste		jb main.4			# No
79f7eb23eeSEd Maste		movb NHRDRV,%dh			# Calculate the highest
80f7eb23eeSEd Maste		addb $0x80,%dh			#  drive number available
81f7eb23eeSEd Maste		cmpb %dh,%dl			# Within range?
82f7eb23eeSEd Maste		jb main.5			# Yes
83f7eb23eeSEd Mastemain.4: 	movb (%si),%dl			# Load drive
84f7eb23eeSEd Maste#
85f7eb23eeSEd Maste# Ok, now that we have a valid drive and partition entry, load the CHS from
86f7eb23eeSEd Maste# the partition entry and read the sector from the disk.
87f7eb23eeSEd Maste#
88f7eb23eeSEd Mastemain.5:		movw %sp,%di			# Save stack pointer
89f7eb23eeSEd Maste		movb 0x1(%si),%dh		# Load head
90f7eb23eeSEd Maste		movw 0x2(%si),%cx		# Load cylinder:sector
91f7eb23eeSEd Maste		movw $LOAD,%bx			# Transfer buffer
92f7eb23eeSEd Maste		testb $FL_PACKET,flags		# Try EDD?
93f7eb23eeSEd Maste		jz main.7			# No.
94f7eb23eeSEd Maste		pushw %cx			# Save %cx
95f7eb23eeSEd Maste		pushw %bx			# Save %bx
96f7eb23eeSEd Maste		movw $0x55aa,%bx		# Magic
97f7eb23eeSEd Maste		movb $0x41,%ah			# BIOS:	EDD extensions
98f7eb23eeSEd Maste		int $0x13			#  present?
99f7eb23eeSEd Maste		jc main.6			# No.
100f7eb23eeSEd Maste		cmpw $0xaa55,%bx		# Magic ok?
101f7eb23eeSEd Maste		jne main.6			# No.
102f7eb23eeSEd Maste		testb $0x1,%cl			# Packet mode present?
103f7eb23eeSEd Maste		jz main.6			# No.
104f7eb23eeSEd Maste		popw %bx			# Restore %bx
105f7eb23eeSEd Maste		pushl $0x0			# Set the LBA
106f7eb23eeSEd Maste		pushl 0x8(%si)			#  address
107f7eb23eeSEd Maste		pushw %es			# Set the address of
108f7eb23eeSEd Maste		pushw %bx			#  the transfer buffer
109f7eb23eeSEd Maste		pushw $0x1			# Read 1 sector
110f7eb23eeSEd Maste		pushw $0x10			# Packet length
111f7eb23eeSEd Maste		movw %sp,%si			# Packer pointer
112f7eb23eeSEd Maste		movw $0x4200,%ax		# BIOS:	LBA Read from disk
113f7eb23eeSEd Maste		jmp main.8			# Skip the CHS setup
114f7eb23eeSEd Mastemain.6:		popw %bx			# Restore %bx
115f7eb23eeSEd Maste		popw %cx			# Restore %cx
116f7eb23eeSEd Mastemain.7:		movw $0x201,%ax			# BIOS: Read from disk
117f7eb23eeSEd Mastemain.8:		int $0x13			# Call the BIOS
118f7eb23eeSEd Maste		movw %di,%sp			# Restore stack
119f7eb23eeSEd Maste		jc err_rd			# If error
120f7eb23eeSEd Maste#
121f7eb23eeSEd Maste# Now that we've loaded the bootstrap, check for the 0xaa55 signature.  If it
122f7eb23eeSEd Maste# is present, execute the bootstrap we just loaded.
123f7eb23eeSEd Maste#
124f7eb23eeSEd Maste		cmpw $MAGIC,0x1fe(%bx)		# Bootable?
125f7eb23eeSEd Maste		jne err_os			# No
126f7eb23eeSEd Maste		jmp *%bx			# Invoke bootstrap
127f7eb23eeSEd Maste#
128f7eb23eeSEd Maste# Various error message entry points.
129f7eb23eeSEd Maste#
130f7eb23eeSEd Masteerr_pt: 	movw $msg_pt,%si		# "Invalid partition
131f7eb23eeSEd Maste		jmp putstr			#  table"
132f7eb23eeSEd Maste
133f7eb23eeSEd Masteerr_rd: 	movw $msg_rd,%si		# "Error loading
134f7eb23eeSEd Maste		jmp putstr			#  operating system"
135f7eb23eeSEd Maste
136f7eb23eeSEd Masteerr_os: 	movw $msg_os,%si		# "Missing operating
137f7eb23eeSEd Maste		jmp putstr			#  system"
138f7eb23eeSEd Maste#
139f7eb23eeSEd Maste# Output an ASCIZ string to the console via the BIOS.
140f7eb23eeSEd Maste#
141f7eb23eeSEd Masteputstr.0:	movw $0x7,%bx	 		# Page:attribute
142f7eb23eeSEd Maste		movb $0xe,%ah			# BIOS: Display
143f7eb23eeSEd Maste		int $0x10			#  character
144f7eb23eeSEd Masteputstr: 	lodsb				# Get character
145f7eb23eeSEd Maste		testb %al,%al			# End of string?
146f7eb23eeSEd Maste		jnz putstr.0			# No
147f7eb23eeSEd Masteputstr.1:	jmp putstr.1			# Await reset
148f7eb23eeSEd Maste
149f7eb23eeSEd Mastemsg_pt: 	.asciz "Invalid partition table"
150f7eb23eeSEd Mastemsg_rd: 	.asciz "Error loading operating system"
151f7eb23eeSEd Mastemsg_os: 	.asciz "Missing operating system"
152f7eb23eeSEd Maste
153f7eb23eeSEd Maste		.org PT_OFF-1,0x90
154f7eb23eeSEd Masteflags:		.byte FLAGS			# Flags
155f7eb23eeSEd Maste
156f7eb23eeSEd Mastepartbl: 	.fill 0x10,0x4,0x0		# Partition table
157f7eb23eeSEd Maste		.word MAGIC			# Magic number
158