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