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