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
|
bits 16
jmp start
CR equ 0Dh
LF equ 0Ah
K_CS_ADDR equ 0050h
; 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
; 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
start:
cli
mov ax, 07C0h ; load bootstrap address
mov ds, ax ; set data segment
mov es, ax ; set extra segment
mov ax, stack_end ; load address of temp stack segment
mov ss, ax ; set stack end
mov cx, 01FCh
sub ax, cx
mov sp, ax ; set stack top before boot signature
sti
mov [drive0], dx ; save first detected drive
push banner ;
call puts ; print version
add sp, 2 ; clean up
push word [drive0]
call disk_reset
add sp, 2
push msg_loading
call puts
add sp, 2
; begin disk operations
xor cx, cx
mov ax, K_CS_ADDR
mov es, ax
mov bx, 0000h ; starting address (es:bx)
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, 0200h ; increment address by 512 bytes
inc di ; increment track read count
cmp di, 12h ; transfer 9K (512 * 18)
jle .loader ; keep reading
push msg_done
call puts
add sp, 2
mov dx, [drive0] ; the kernel will need the boot drive number
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:
mov ah, 00h ; reset disk
; dl is drive number
int 13h ; BIOS disk service
jnc .success
push error_msg_disk_reset
call panic
.success:
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
call disk_reset
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
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
stack_end: ; address of stack end
; boot signature
times 510-($-$$) db 0
dw 0xAA55
|