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 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
cmpb $0xff,%dh # Might we need to use LBA?
jnz main.7 # No.
cmpw $0xffff,%cx # Do we need to use LBA?
jnz 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
partbl: .fill 0x10,0x4,0x0 # Partition table
.word MAGIC # Magic number
|