-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmbr.asm
224 lines (189 loc) · 3.49 KB
/
mbr.asm
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
bits 16
%include "bdr.inc"
section .text
org mbr_start
jmp 0:main_10
main_10:
mov ax,cs
mov ss,ax
xor sp,sp
mov ds,ax
mov es,ax
cld
sti
mov bp,mbr_vars_start
; first, try boot drive
mov [bp+edd.drive],dl
call check
jz main_60
mov ah,8
xor di,di
mov dl,80h
call int_13
jnc main_20
mov dl,1 ; we'll try at least one
main_20:
cmp dl,1 ; dto
mov al,80h
adc dl,al
mov [bp+bios_drives],dl
main_30:
mov [bp+edd.drive],al
call check
jz main_60
mov al,[bp+edd.drive]
inc ax
cmp al,[bp+bios_drives]
jb main_30
; too bad, not found
mov si,msg_not_found
jmp final_msg
main_60:
; ok, we got it
mov si,msg_ok
call print
mov bx,disk_read
call disk_buf + sht.sizeof + bht.sizeof
mov si,msg_no_msg
jmp final_msg
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;
; return:
; ZF: 1 ok; 0 not ok
;
check:
mov word [bp+edd.count],1
mov si,start_sector
lea di,[bp+edd.sector]
movsd
movsd
call disk_read
sbb cx,cx
jnz check_90
mov si,disk_buf+sht.id
mov di,id
mov cl,4 ; cx was 0
rep cmpsw
jnz check_90
xor dx,dx
mov ch,1 ; cx was 0
mov si,disk_buf
check_50:
lodsw
add dx,ax
loop check_50
check_90:
ret
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
disk_read:
mov dword [bp+edd.buf],disk_buf << 12
mov ah,41h
mov bx,55aah
call int_13
jc disk_read_chs
cmp bx,0aa55h
jnz disk_read_chs
test cl,1
jz disk_read_chs
disk_read_edd:
lea si,[bp+edd.packet]
mov word [si],10h
mov ah,42h
jmp int_13
disk_read_chs:
; classic interface; but if block number turns out
; to be too big, try edd anyway
cmp dword [bp+edd.sector+4],0
jnz disk_read_edd
mov ah,8
xor di,di
call int_13
jc disk_read_chs_90
mov ax,cx
shr cl,6
xchg cl,ch
and al,3fh
inc dh
mov bl,al
mul dh
; ax = s*h
xchg ax,di
mov ax,[bp+edd.sector]
mov dx,[bp+edd.sector+2]
cmp dx,di
jae disk_read_edd
div di
; ax = c, dx = s*h
cmp ax,cx
ja disk_read_edd
shl ah,6
xchg al,ah
xchg ax,dx
; dx = c
div bl
; ah = s-1, al = h
add dl,ah
inc dx
mov ch,al
xchg cx,dx
mov al,[bp+edd.count]
les bx,[bp+edd.buf]
mov ah,2
call int_13
push word 0
pop es
disk_read_chs_90:
ret
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int_13:
mov dl,[bp+edd.drive]
push bp
int 13h
pop bp
ret
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
final_msg:
call print
mov si,msg_next
call print
mov ah,0
int 16h
mov si,msg_nl
call print
int 19h
final_msg_10:
hlt
jmp final_msg_10
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Write string.
;
; si text
;
; return:
;
print:
lodsb
or al,al
jz print_90
mov bx,7
mov ah,14
; maybe save bp?
int 10h
jmp print
print_90:
ret
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
msg_ok db "ok", 13, 10, 0
msg_not_found db "Boot drive not found."
msg_nl db 13, 10
msg_no_msg db 0
msg_next db 10, "Press a key to continue boot sequence.", 0
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
%if ($ - $$) > 1a8h
%error "mbr too big"
%endif
mbr_fill times 1a8h - ($ - $$) db 0
start_sector dd 0, 0
id dd 0, 0
times 1feh - ($ - $$) db 0
dw 0aa55h