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