FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
MS-DOS-kernel/boot/boot32lb.asm at master · Programuserbash/MS-DOS-kernel · GitHub
Programuserbash
/
MS-DOS-kernel
Public
forked from
FDOS/kernel
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
MS-DOS-kernel
/
boot
/
boot32lb.asm
Copy path
More file actions
More file actions
Latest commit
History
History
History
428 lines (342 loc) · 12.3 KB
Breadcrumbs
MS-DOS-kernel
/
boot
/
boot32lb.asm
Copy path
File metadata and controls
428 lines (342 loc) · 12.3 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
; This is an LBA-enabled FreeDOS FAT32 boot sector (single sector!).
; You can use and copy source code and binaries under the terms of the
; GNU Public License (GPL), version 2 or newer. See www.gnu.org for more.
; Based on earlier work by FreeDOS kernel hackers, modified heavily by
; Eric Auer and Jon Gentle in 7 / 2003.
;
; Features: Uses LBA and calculates all variables from BPB/EBPB data,
; thus making partition move / resize / image-restore easier. FreeDOS
; can boot from FAT32 partitions which start > 8 GB boundary with this
; boot sector. Disk geometry knowledge is not needed for booting.
;
; Windows uses 2-3 sectors for booting (sector stage, statistics sector,
; filesystem stage). Only using 1 sector for FreeDOS makes multi-booting
; of FreeDOS and Windows on the same filesystem easier.
;
; Requirements: LBA BIOS and 386 or better CPU. Use the older CHS-only
; boot sector if you want FAT32 on really old PCs (problems: you cannot
; boot from > 8 GB boundary, cannot move / resize / ... without applying
; SYS again if you use the CHS-only FAT32 boot sector).
;
; FAT12 / FAT16 hints: Use the older CHS-only boot sector unless you
; have to boot from > 8 GB. The LBA-and-CHS FAT12 / FAT16 boot sector
; needs applying SYS again after move / resize / ... a variant of that
; boot sector without CHS support but with better move / resize / ...
; support would be good for use on LBA harddisks.
; Memory layout for the FreeDOS FAT32 single stage boot process:
;
; ...
; |-------| 1FE0h:7E00h = 27C00h (159 KiB)
; |BOOTSEC| loader relocates itself here first thing,
; |RELOC. | before loading root directory/FAT/kernel file
; |-------| 1FE0h:7C00h = 27A00h (158 KiB)
; | STACK | below relocated loader, above FAT sector (size 22 KiB)
; ...
; |-------| 2200h:2000h = 24000h (144 KiB)
; | FAT | (only 1 sector buffered, maximum sector size 8 KiB)
; |-------| 2200h:0000h = 22000h (136 KiB)
; ...
; |-------| 0000h:7E00h = 07E00h (31.5 KiB)
; |BOOTSEC| overwritten by the kernel, so the
; |ORIGIN | bootsector relocates itself up...
; |-------| 0000h:7C00h = 07C00h (31 KiB)
; ...
; |-------|
; |KERNEL | maximum size 128 KiB (overwrites bootsec origin)
; |LOADED | (holds 1 sector directory buffer before kernel file load)
; |-------| 0060h:0000h = 00600h (1.5 KiB)
; ...
; The kernel load segment may be patched using the SYS /L switch.
; We support values between 0x60 and 0x200 here, with file size
; of up to 128 KiB (rounded to cluster size). Default is 0x60.
; NOTE: sys must be updated if magic offsets change
%assign
ISFAT1216DUAL
0
%include
"magic.mac"
segment .text
org
0x7c00
; this is a boot sector
Entry:
jmp
short real_start
nop
; bp is initialized to 7c00h
; %define bsOemName bp+0x03 ; OEM label (8)
%define
bsBytesPerSec
bp
+
0x0b
; bytes/sector (dw)
%define
bsSecPerClust
bp
+
0x0d
; sectors/allocation unit (db)
%define
bsResSectors
bp
+
0x0e
; # reserved sectors (dw)
%define
bsFATs
bp
+
0x10
; # of fats (db)
; %define bsRootDirEnts bp+0x11 ; # of root dir entries (dw, 0 for FAT32)
; (FAT32 has root dir in a cluster chain)
; %define bsSectors bp+0x13 ; # sectors total in image (dw, 0 for FAT32)
; (if 0 use nSectorHuge even if FAT16)
; %define bsMedia bp+0x15 ; media descriptor: fd=2side9sec, etc... (db)
; %define sectPerFat bp+0x16 ; # sectors in a fat (dw, 0 for FAT32)
; (FAT32 always uses xsectPerFat)
%define
sectPerTrack
bp
+
0x18
; # sectors/track
; %define nHeads bp+0x1a ; # heads (dw)
%define
nHidden
bp
+
0x1c
; # hidden sectors (dd)
; %define nSectorHuge bp+0x20 ; # sectors if > 65536 (dd)
%define
xsectPerFat
bp
+
0x24
; Sectors/Fat (dd)
; +0x28 dw flags (for fat mirroring)
; +0x2a dw filesystem version (usually 0)
%define
xrootClst
bp
+
0x2c
; Starting cluster of root directory (dd)
; +0x30 dw -1 or sector number of fs.-info sector
; +0x32 dw -1 or sector number of boot sector backup
; (+0x34 .. +0x3f reserved)
%define
drive
bp
+
0x40
; Drive number
%define
loadsegoff_60
bp
+
loadseg_off
-
Entry
%define
LOADSEG
0x0060
%define
FATSEG
0x2200
%define
fat_secshift fat_afterss
-
1
; each fat sector describes 2^??
; clusters (db) (selfmodifying)
%define
fat_sector
bp
+
0x44
; last accessed FAT sector (dd)
; (overwriting unused bytes)
%define
fat_start
bp
+
0x48
; first FAT sector (dd)
; (overwriting unused bytes)
%define
data_start
bp
+
0x4c
; first data sector (dd)
; (overwriting unused bytes)
times
52h
-
($
-
$$) db
0
; The filesystem ID is used by lDOS's instsect (by ecm)
; by default to validate that the filesystem matches.
db
"FAT32"
times
5Ah
-
($
-
$$) db
32
; not used: [0x42] = byte 0x29 (ext boot param flag)
; [0x43] = dword serial
; [0x47] = label (padded with 00, 11 bytes)
; [0x52] = "FAT32",32,32,32 (not used by Windows)
; ([0x5a] is where FreeDOS parts start)
;-----------------------------------------------------------------------
; ENTRY
;-----------------------------------------------------------------------
real_start:
cld
cli
sub
ax
,
ax
mov
ds
,
ax
mov
bp
,
0x7c00
mov
ax
,
0x1FE0
mov
es
,
ax
mov
si
,
bp
mov
di
,
bp
mov
cx
,
0x0100
rep
movsw
; move boot code to the 0x1FE0:0x0000
jmp
word
0x1FE0
:cont
loadseg_off dw
0
magicoffset
"loadseg"
,
78h
dw
LOADSEG
; -------------
cont:
mov
ds
,
ax
mov
ss
,
ax
; stack and BP-relative moves up, too
lea
sp
,
[
bp
-
0x20
]
sti
magicoffset
"set unit"
,
82h
mov
[
drive
],
dl
; BIOS passes drive number in DL
%ifndef
QUIET
mov
si
,
msg_LoadFreeDOS
call
print
; modifies AX BX SI
%else
; ensure code after this still at same location
times
6
nop
%endif
; -------------
; CALCPARAMS: figure out where FAT and DATA area starts
; (modifies EAX EDX, sets fat_start and data_start variables)
calc_params:
xor
eax
,
eax
mov
[
fat_sector
],
eax
; init buffer status
; first, find fat_start:
mov
ax
,
[
bsResSectors
]
; no movzx eax, word... needed
add
eax
,
[
nHidden
]
mov
[
fat_start
],
eax
; first FAT sector
mov
[
data_start
],
eax
; (only first part of value)
; next, find data_start:
mov
eax
,
[
bsFATs
]
; no movzx ... byte needed:
; the 2 dw after the bsFATs db are 0 by FAT32 definition :-).
imul
dword
[
xsectPerF
at
]
; (also changes edx)
add
[
data_start
],
eax
; first DATA sector
; (adding in RAM is shorter!)
; finally, find fat_secshift:
mov
ax
,
512
; default sector size (means default shift)
; shift = log2(secSize) - log2(fatEntrySize)
;--- mov cl, 9-2 ; shift is 7 for 512 bytes per sector
fatss_scan:
cmp
ax
,
[
bsBytesPerSec
]
jz
fatss_found
add
ax
,
ax
;--- inc cx
inc
word
[
fat_secshift
]
;XXX ; initially 9-2 (byte!)
jmp
short fatss_scan
; try other sector sizes
fatss_found:
;--- mov [fat_secshift], cl
; -------------
; FINDFILE: Searches for the file in the root directory.
; Returns: EAX = first cluster of file
mov
eax
,
[
xrootClst
]
; root dir cluster
ff_next_clust:
push
eax
; save cluster
call
convert_cluster
jc
boot_error
; EOC encountered
; EDX is clust/sector, EAX is sector
ff_next_sector:
les
bx
,
[
loadsegoff_60
]
; load to loadseg:0
call
readDisk
;--- push eax ; save sector
;--- xor ax, ax ; first dir. entry in this sector
xor
di
,
di
;XXX
; Search for KERNEL.SYS file name, and find start cluster.
ff_next_entry:
mov
cx
,
11
mov
si
,
filename
;--- mov di, ax
repe
cmpsb
jz
ff_done
; note that di now is at dirent+11
;--- add ax, 0x20 ; next directory entry
;--- cmp ax, [bsBytesPerSec] ; end of sector reached?
add
di
,
byte
0x20
;XXX
and
di
,
byte
-
0x20
; 0xffe0 ;XXX
cmp
di
,
[
bsBytesPerSec
]
;XXX
jnz
ff_next_entry
;--- pop eax ; restore sector
dec
dx
; next sector in cluster
jnz
ff_next_sector
ff_walk_f
at
:
pop
eax
; restore current cluster
call
next_cluster
; find next cluster
jmp
ff_next_clust
ff_done:
push
word
[
es
:
di
+
0x14
-
11
]
; get cluster number HI
push
word
[
es
:
di
+
0x1A
-
11
]
; get cluster number LO
pop
eax
; convert to 32bit
sub
bx
,
bx
; ES points to LOADSEG
; (kernel -> ES:BX)
; -------------
read_kernel:
push
eax
call
convert_cluster
jc
boot_success
; EOC encountered - done
; EDX is sectors in cluster, EAX is sector
rk_in_cluster:
call
readDisk
dec
dx
jnz
rk_in_cluster
; loop over sect. in cluster
rk_walk_f
at
:
pop
eax
call
next_cluster
jmp
read_kernel
;-----------------------------------------------------------------------
boot_success:
mov
dl
,
[
drive
]
; for Enhanced DR-DOS load
mov
bl
,
dl
; for FreeDOS load
jmp
far
[
loadsegoff_60
]
;-----------------------------------------------------------------------
boot_error:
mov
si
,
msg_BootError
call
print
; modifies AX BX SI
wait_key:
xor
ah
,
ah
int
0x16
; wait for a key
reboot:
int
0x19
; reboot the machine
;-----------------------------------------------------------------------
; given a cluster number, find the number of the next cluster in
; the FAT chain. Needs fat_secshift and fat_start.
; input: EAX - cluster
; output: EAX - next cluster
next_cluster:
push
es
push
di
push
bx
mov
di
,
ax
shl
di
,
2
; 32bit FAT
push
ax
mov
ax
,
[
bsBytesPerSec
]
dec
ax
and
di
,
ax
; mask to sector size
pop
ax
shr
eax
,
7
; e.g. 9-2 for 512 by/sect.
fat_afterss:
; selfmodifying code: previous byte is patched!
; (to hold the fat_secshift value)
add
eax
,
[
fat_start
]
; absolute sector number now
mov
bx
,
FATSEG
mov
es
,
bx
sub
bx
,
bx
cmp
eax
,
[
fat_sector
]
; already buffered?
jz
cn_buffered
mov
[
fat_sector
],
eax
; number of buffered sector
call
readDisk
cn_buffered:
and
byte
[
es
:
di
+
3
],
0x0f
; mask out top 4 bits
mov
eax
,
[
es
:
di
]
; read next cluster number
pop
bx
pop
di
pop
es
ret
;-----------------------------------------------------------------------
; Convert cluster number to the absolute sector number
; ... or return carry if EndOfChain! Needs data_start.
; input: EAX - target cluster
; output: EAX - absolute sector
; EDX - [bsSectPerClust] (byte)
; carry clear
; (if carry set, EAX/EDX unchanged, end of chain)
convert_cluster:
cmp
eax
,
0x0ffffff8
; if end of cluster chain...
jnb
end_of_chain
; sector = (cluster-2) * clustersize + data_start
dec
eax
dec
eax
movzx
edx
,
byte
[
bsSecPerClust
]
dec
dl
; spc - 1
inc
dx
; spc
push
edx
mul
edx
pop
edx
add
eax
,
[
data_start
]
; here, carry is unset (unless parameters are wrong)
ret
end_of_chain:
stc
; indicate EOC by carry
ret
;-----------------------------------------------------------------------
; PRINT - prints string DS:SI
; modifies AX BX SI
printchar:
xor
bx
,
bx
; video page 0
mov
ah
,
0x0e
; print it
int
0x10
; via TTY mode
print:
lodsb
; get token
cmp
al
,
0
; end of string?
jne
printchar
; until done
ret
; return to caller
;-----------------------------------------------------------------------
; Read a sector from disk, using LBA
; input: EAX - 32-bit DOS sector number
; ES:BX - destination buffer
; (will be filled with 1 sector of data)
; output: ES:BX points one byte after the last byte read.
; EAX - next sector
readDisk:
push
dx
push
si
push
di
read_next:
push
eax
; would ax be enough?
mov
di
,
sp
; remember parameter block end
;--- db 0x66 ; operand size override (push dword)
push
byte
0
;XXX ; other half of the 32 bits at [C]
; (did not trust "o32 push byte 0" opcode)
push
byte
0
; [C] sector number high 32bit
push
eax
; [8] sector number low 32bit
push
es
; [6] buffer segment
push
bx
; [4] buffer offset
push
byte
1
; [2] 1 sector (word)
push
byte
16
; [0] size of parameter block (word)
mov
si
,
sp
mov
dl
,
[
drive
]
mov
ah
,
42h
; disk read
int
0x13
mov
sp
,
di
; remove parameter block from stack
; (without changing flags!)
pop
eax
; would ax be enough?
jnc
read_ok
; jump if no error
push
ax
; !!
xor
ah
,
ah
; else, reset and retry
int
0x13
pop
ax
; !!
jmp
read_next
read_ok:
inc
eax
; next sector
add
bx
,
word
[
bsBytesPerSec
]
jnc
no_incr_es
; if overflow...
mov
dx
,
es
add
dh
,
0x10
; ...add 1000h to ES
mov
es
,
dx
no_incr_es:
pop
di
pop
si
pop
dx
ret
;-----------------------------------------------------------------------
msg_LoadFreeDOS db
"Loading FreeDOS "
,
0
times
0x01ee
-
$
+
$$ db
0
msg_BootError db
"No "
; currently, only "kernel.sys not found" gives a message,
; but read errors in data or root or fat sectors do not.
magicoffset
"kernel name"
,
1F1h
filename db
"KERNEL SYS"
sign dw
0
,
0xAA55
; Win9x uses all 4 bytes as magic value here.
Back
|
FazBrowse Home
|
New Git URL