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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
bits 16
jmp start
CR equ 0Dh
LF equ 0Ah
K_CS_ADDR equ 07E0h
start:
mov ax, 07c0h
mov ds, ax ; set data segment
mov ax, 07e0h
mov ss, ax ; set stack segment
mov sp, 2000h ; 8192k
push bp ; set up stack frame
mov bp, sp
sub sp, 2 ; local storage
mov [drive0], dl ; save first detected drive
call cls ; clear screen
push 0 ;
call setcursor ; set cursor position
push banner ;
call puts ; print version
add sp, 2 ; clean up
push word [drive0]
call disk_reset
add sp, 2
xor cx, cx
mov ax, K_CS_ADDR
mov es, ax
push msg_loading
call puts
add sp, 2
mov bx, 0
mov di, 2 ; start at sector
.loader:
mov al, 1 ; read one sector
mov cx, di ; track/cyl | sector number
mov dh, 0 ; head number
mov dl, [drive0] ; drive number
call disk_read
push '.'
call putc
add sp, 2
add bx, 200h ; increment address by 512 bytes
inc di ; increment sector read count
cmp di, 16 ; 8K (i'll make this smarter later)
jle .loader ; keep reading
push msg_done
call puts
add sp, 2
add sp, 2 ; remove local storage
mov sp, bp
pop bp
mov dx, [drive0] ; the kernel will need the boot drive number
;cli ; disable interrupts
;mov ax, K_CS_ADDR ; get code segment
;mov ds, ax ; set data segment
;mov es, ax ; set extra segment
;mov ax, 0800h
;mov ss, ax ; set stack segment
;mov sp, 0ffffh ; set stack pointer (~64k)
jmp K_CS_ADDR:0000h ; jump to kernel address
cli ; disable interrupts
jmp $ ; hang
panic:
; Hang system with supplied error message
push bp
mov bp, sp
push error_msg_panic ; i.e. 'PANIC:'
call puts
add sp, 2
push word [bp + 4] ; address of error string buffer
call puts ; print error
add sp, 2
cli ; disable interrupts
jmp $ ; hang (no return)
; stack is dead
disk_reset:
push bp
mov bp, sp
pusha
mov ah, 00h ; reset disk
mov dl, [bp + 4] ; disk number
int 13h ; BIOS disk service
jnc .success
push error_msg_disk_reset
call panic
.success:
popa
mov sp, bp
pop bp
ret
disk_read:
push bp
mov bp, sp
push di
mov di, 3 ; retry counter
.readloop:
push ax
push bx
push cx
mov ah, 02h ; BIOS - read disk sectors
int 13h ; BIOS disk service
jnc .success
push dx
call disk_reset
add sp, 2
pop cx
pop bx
pop ax
dec di
jnz .readloop
push error_msg_disk_read
call panic
add sp, 2
.success:
pop di
mov sp, bp
pop bp
ret
cls:
push bp
mov bp, sp
pusha
mov ah, 07h ; BIOS - scroll down
mov al, 00h ; lines to scroll (0 == entire screen)
mov bx, 0700h ; color white/black
; & video page zero
mov cx, 0
mov dh, 24 ; rows
mov dl, 79 ; cols
int 10h ; BIOS video service
popa
mov sp, bp
pop bp
ret
setcursor:
push bp
mov bp, sp
pusha
mov ah, 02h ; BIOS - set cursor position
mov bh, 0 ; video page zero
mov dx, [bp + 4] ; address of new cursor value
int 10h ; BIOS video service
popa
mov sp, bp
pop bp
ret
putc:
; Write single character at cursor position
push bp
mov bp, sp
pusha
mov ah, 0eh ; BIOS - teletype
mov al, [bp + 4] ; character
mov bx, 0 ; video page zero
int 10h ; BIOS video service
popa
mov sp, bp
pop bp
ret
puts:
; Write string buffer at cursor position
push bp
mov bp, sp
pusha
mov si, [bp + 4] ; address of string buffer
mov bx, 0000h ;
mov ah, 0eh ; BIOS - teletype
.loop:
lodsb ; load byte at [si] into al
or al, 0 ; 0 | 0 = 0 (detect null terminator)
je .end
int 10h ; BIOS video service
jmp .loop
.end:
popa
mov sp, bp
pop bp
ret
; data
drive0: dw 0
banner: db "MINOS Bootloader", CR, LF, 0
; General messages
msg_loading: db "Loading", 0
msg_done: db "done!", CR, LF, 0
msg_disk_reset: db "Drive reset successful.", CR, LF, 0
msg_disk_read: db "Sector read successful.", CR, LF, 0
; Error messages
error_msg_panic: db "PANIC: ", 0
error_msg_disk_reset: db "Drive reset failed!", CR, LF, 0
error_msg_disk_read: db "Drive read failed!", CR, LF, 0
; boot signature
times 510-($-$$) db 0
dw 0xAA55
|