-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstage1.asm
More file actions
237 lines (194 loc) · 5.02 KB
/
stage1.asm
File metadata and controls
237 lines (194 loc) · 5.02 KB
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
%include "io.asm"
COM1 equ 0x3f8
COMTEST_TRIES equ 10000
; Floppy controller Digital Output Register
FLOPPY_DOR equ 0x3f2
extern stage2_start
extern stage2_size
; Print one charecter in AL
; Uses: AX, BX
%macro PrintCharBios 0
mov bh, 0
mov ah, 0x0e ; Teletype Output
int 0x10 ; IN: AH = 0x0E
; AL = character
; BH = page num
; BL = foreground color (video only)
%endmacro
; Print one charecter in AL
; Uses: AX, DX
%macro PrintCharCom 0
mov ah, al
%%loop:
inb COM1 + 5 ; read Line Status Register
and al, 0x20 ; check if Transmitter holding register empty is set
jz %%loop
mov al, ah
outb COM1, al
%endmacro
; Print one charecter in AL
%macro PrintChar 1
push ax
push bx
push dx
mov al, %1
PrintCharCom
PrintCharBios
pop dx
pop bx
pop ax
%endmacro
[BITS 16]
start:
jmp 0x0:start2 ; set up cs
start2:
xor ax, ax
mov ds, ax
mov ss, ax ; stack segment
mov sp, 0x7bfe ; stack is before the bootloader (16 bit align)
mov [bootdisk], dl
cld
outb COM1 + 1, 0x00 ; disable interrupts
outb COM1 + 3, 0x80 ; set DLAB (Divisor Latch Access Bit)
outb COM1 + 0, 0x0c ; set divisor to 12 (9600 baud), low byte
outb COM1 + 1, 0x00 ; high byte
outb COM1 + 3, 0x03 ; clear DLAB, no parity, stop bits 1, data bits 8
outb COM1 + 2, 0xc7 ; 14 byte trigger, clear tx & rx FIFO, enable FIFO
outb COM1 + 4, 0x1f ; loopback, ena OUT2, ena OUT1, RTS set, DTR set
outb COM1 + 0, 0xae ; send test byte
; It seems that real hardware (at least Asus CUSL2-C) requires some time
; to be able to return the test byte
mov cx, COMTEST_TRIES
.comtest_loop:
inb COM1 + 5 ; read Line Status Register
and al, 0x1
jnz .comtest_ok ; test if data available
loop .comtest_loop
jmp hang
.comtest_ok:
outb COM1 + 4, 0x0f ; normal operation, ena OUT2, ena OUT1, RTS set, DTR set
mov ax, rst_disk
call LogString
mov ah, 0x0 ; reset disks
mov dl, [bootdisk]
int 0x13 ; Input AH = 0, DL disk number
; DL set by the BIOS
jc some_err
mov ax, done
call LogString
mov ax, read_disk
call LogString
; calculate stage2 size in sectors
mov ax, stage2_size
add ax, 512 - 1
shr ax, 9 ; div 512
push ax ; push stage2 size in sectors
mov ch, 0 ; cylinder
mov cl, 2 ; sector
mov dh, 0 ; head
mov dl, [bootdisk] ; bootdisk set by BIOS
mov ax, 0 ; stage2 segment
mov es, ax
mov bx, stage2_start ; stage2 offsett
read_loop:
mov ah, 0x02 ; read sectors
mov al, 1 ; read 1 sector
int 0x13 ; Input: AH = 0x02
; AL = num of sectors to read
; CH = cylinder number
; CL = sector number (0-5 bits)
; DH = head number
; DL = drive number
; ES:BX = data buffer
; Out: CF set on error / CF clear on successful
; AH = status
; AL = number of sectors read
jc some_err
.offset_check:
add bx, 512 ; next memory location
jc .offset_roll
.sector_check:
cmp cl, 18
je .sector_roll
inc cl ; next sector
.head_check:
cmp dh, 2
jnb .head_roll
.cylinder_check:
cmp ch, 80
jnb .cylinder_roll
jmp .cont_read
; ========== ROLLOVERS ==========
.offset_roll:
mov bx, es
add bx, 0x1000
mov es, bx
xor bx, bx
jmp .sector_check
.sector_roll:
mov cl, 1 ; back to sector 1
inc dh ; next head
jmp .head_check
.head_roll:
xor dh, dh ; back to head 0
inc ch ; next cylinder
jmp .cylinder_check
.cylinder_roll:
xor ch, ch ; back to cylinder 0
; ========== ROLLOVERS END ==========
.cont_read:
PrintChar "."
mov si, cx ; save ch/cl
pop cx
dec cx ; dec remaining sectors
push cx ; restore ch/cl
mov cx, si
jnz read_loop
pop cx ; just to clear the stack
mov ax, done
call LogString
jmp jump_stage2
some_err:
mov ax, err
call LogString
hang:
mov ax, hang_msg
call LogString
jmp $
jump_stage2:
; shutdown floppy motors
inb FLOPPY_DOR
and al, 0x0f ; clear all 4 motor ON flags
outb FLOPPY_DOR, al
mov ax, jump_stage
call LogString
jmp 0x0:stage2_start
; Log the specified string to COM1 and the screen
; In: AX: string ptr
LogString:
push si
push bx
push dx
mov si, ax
.loop:
lodsb
or al, al
jz .done
PrintCharCom
PrintCharBios
jmp .loop
.done:
pop dx
pop bx
pop si
ret
rst_disk db 'Reset disks ', 0
read_disk db 'Read ', 0
done db 'OK', 13, 10, 0
err db 'Err', 13, 10, 0
hang_msg db 'hang', 13, 10, 0
jump_stage db 'JMP stage2', 13, 10, 0
bootdisk db 0
times 510-($-$$) db 0xcc
db 0x55
db 0xAA