This repository has been archived by the owner on Aug 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathboot.s
270 lines (235 loc) · 4.27 KB
/
boot.s
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
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
[bits 16]
[org 0x7C00]
[cpu 386]
; Memory map:
; 0x500-0x700: filesystem header
; 0x700-0x900: sector table buffer
; 0x900-0xB00: file sector buffer
; 0x7000-0x7C00: stack
; 0x7C00-0x7E00: this code
; 0x10000-0x20000: loaded program
start:
; Setup segment registers and the stack.
cli
xor ax,ax
mov ds,ax
mov ss,ax
mov sp,0x7C00 ; Put stack below the code.
sti
cld
jmp 0x0000:.set_cs
.set_cs:
; Save the BIOS drive number.
mov [drive_number],dl
; Print a loading message.
mov si,loading_message
call print_string
; Get drive parameters.
mov ah,0x08
mov dl,[drive_number]
xor di,di
int 0x13
mov si,error_read
jc error
and cx,31
mov [max_sectors],cx
inc dh
shr dx,8
mov [max_heads],dx
; Load the filesystem header.
xor ax,ax
mov es,ax
mov di,1
mov bx,0x500
call load_sector
; Check for correct signature and version.
mov si,error_disk
mov ax,[0x500]
cmp ax,0x706C
jne error
mov ax,[0x502]
cmp ax,1
jne error
; Load the root directory.
mov ax,[0x51C]
mov [file_remaining_size],ax
mov ax,[0x520]
mov [current_sector],ax
mov di,ax
xor ax,ax
mov es,ax
mov bx,0x900
call load_sector
; Scan the root directory.
xor bx,bx
.scan_root_directory:
cmp bx,0x200
jne .loaded_sector
call next_file_sector
xor bx,bx
.loaded_sector:
; Compare file name.
xor ax,ax
mov es,ax
mov cx,7
mov si,program_name
mov di,0x900
add di,bx
rep cmpsb
jne .next_entry
; Save the startup program's first sector, size and checksum.
mov al,[0x917 + bx]
mov [checksum],al
mov ax,[0x910 + bx]
mov [file_remaining_size],ax
mov di,[0x914 + bx]
mov [current_sector],di
jmp .load_startup_program
; Go to the next entry.
.next_entry:
add bx,0x20
sub word [file_remaining_size],0x20
cmp word [file_remaining_size],0
jne .scan_root_directory
mov si,error_disk
jmp error
; Load the startup program.
.load_startup_program:
xor bx,bx
mov es,bx
mov bx,0x900
call load_sector
; Copy the sector to the destination.
.copy_sector:
mov bx,0x1000
mov es,bx
mov di,[file_destination]
mov si,0x900
mov cx,0x200
rep movsb
; Calculate checksum.
mov bl,[checksum]
mov si,0x900
mov cx,0x200
.checksum_loop:
lodsb
xor bl,al
loop .checksum_loop
mov [checksum],bl
; Load the next sector of the startup program.
add word [file_destination],0x200
mov ax,[file_remaining_size]
cmp ax,0x200
jbe .launch
sub word [file_remaining_size],0x200
call next_file_sector
jmp .copy_sector
; Launch the startup program.
.launch:
mov si,error_disk
cmp byte [checksum],0
jne error
mov dl,[drive_number]
jmp 0x1000:0x0000
next_file_sector:
; Do we need to switch the sector table buffer?
mov ax,[current_sector]
shr ax,8 ; 256 sector table entries per sector
cmp al,[current_sector_table]
je .skip_switch
mov [current_sector_table],al
; Load the new sector table buffer.
add ax,2
mov di,ax
xor bx,bx
mov es,bx
mov bx,0x700
call load_sector
.skip_switch:
; Get the next sector.
mov bx,[current_sector]
and bx,0xFF
shl bx,1
mov di,[0x700 + bx]
mov [current_sector],di
; Load the next sector.
xor bx,bx
mov es,bx
mov bx,0x900
jmp load_sector
; di - LBA.
; es:bx - buffer
load_sector:
mov byte [read_attempts],5
.try_again:
mov si,error_read
mov al,[read_attempts]
or al,al
jz error
dec byte [read_attempts]
; Calculate cylinder and head.
mov ax,di
xor dx,dx
div word [max_sectors]
xor dx,dx
div word [max_heads]
push dx ; remainder - head
mov ch,al ; quotient - cylinder
shl ah,6
mov cl,ah
; Calculate sector.
mov ax,di
xor dx,dx
div word [max_sectors]
inc dx
or cl,dl
; Load the sector.
pop dx
mov dh,dl
mov dl,[drive_number]
mov ax,0x0201
int 0x13
jc .try_again
ret
; ds:si - zero-terminated string.
error:
call print_string
jmp $
; ds:si - zero-terminated string.
print_string:
lodsb
or al,al
jz .done
mov ah,0xE
int 0x10
jmp print_string
.done: ret
file_destination:
dw 0
current_sector_table:
db 0xFF
error_read:
db "Cannot read boot disk.",0
error_disk:
db "Corrupt boot disk.",0
program_name:
db "system",0 ; don't forget to change name length in comparison!
loading_message:
db 'Loading... ',0
times (0x1FE - $ + $$) nop
dw 0xAA55
; Uninitialised variables outside the boot image.
drive_number:
db 0
read_attempts:
db 0
max_sectors:
dw 0
max_heads:
dw 0
current_sector:
dw 0
file_remaining_size:
dw 0
checksum:
db 0