Subversion Repositories Kolibri OS

Rev

Rev 1065 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1065 Lrz 1
; Copyright (c) 2008-2009, diamond
2
; All rights reserved.
3
;
4
; Redistribution and use in source and binary forms, with or without
5
; modification, are permitted provided that the following conditions are met:
6
;       * Redistributions of source code must retain the above copyright
7
;       notice, this list of conditions and the following disclaimer.
8
;       * Redistributions in binary form must reproduce the above copyright
9
;       notice, this list of conditions and the following disclaimer in the
10
;       documentation and/or other materials provided with the distribution.
11
;       * Neither the name of the  nor the
12
;       names of its contributors may be used to endorse or promote products
13
;       derived from this software without specific prior written permission.
14
;
15
; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka  ''AS IS'' AND ANY
16
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
; DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
19
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
;*****************************************************************************
26
 
1132 Lrz 27
        org     0x7E00
1065 Lrz 28
; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here
29
; ss:bp = 0:7C00
30
virtual at bp
1132 Lrz 31
                rb      3               ; BS_jmpBoot
32
                rb      8               ; BS_OEMName, ignored
33
                dw      ?               ; BPB_BytsPerSec
34
BPB_SecsPerClus db      ?
35
BPB_RsvdSecCnt  dw      ?
36
BPB_NumFATs     db      ?
37
BPB_RootEntCnt  dw      ?
38
BPB_TotSec16    dw      ?
39
                db      ?               ; BPB_Media
40
BPB_FATSz16     dw      ?
41
BPB_SecPerTrk   dw      ?
42
BPB_NumHeads    dw      ?
43
BPB_HiddSec     dd      ?
44
BPB_TotSec32    dd      ?
45
BS_DrvNum       db      ?
46
fat_type        db      ?               ; this is BS_Reserved1,
47
                                ; we use it to save FS type: 0=FAT12, 1=FAT16
48
                db      ?               ; BS_BootSig
49
num_sectors     dd      ?               ; BS_VolID
50
;               rb      11              ; BS_VolLab
51
;               rb      3               ; BS_FilSysType, first 3 bytes
52
read_sectors    dw      ?
53
read_sectors2   dw      ?
54
lookup_in_root_dir dw   ?
55
scan_for_filename dw    ?
56
err_             dw      ?
57
noloader        dw      ?
58
cachelimit      dw      ?
59
filesize:       ; will be used to save file size
60
                rb      5               ; BS_FilSysType, last 5 bytes
1065 Lrz 61
; following variables are located in the place of starting code;
62
; starting code is no more used at this point
1132 Lrz 63
sect_per_clus   dw      ?
64
cur_cluster     dw      ?
65
next_cluster    dw      ?
66
flags           dw      ?
67
cur_delta       dd      ?
1065 Lrz 68
end virtual
69
 
70
; procedures from boot sector
71
; LBA version
72
lba_read_sectors = 7CE2h
73
lba_read_sectors2 = 7CDCh
74
lba_lookup_in_root_dir = 7D4Fh
75
lba_scan_for_filename = 7D2Dh
76
lba_err = 7CB5h
77
lba_noloader = 7CB2h
78
; CHS version
79
chs_read_sectors = 7CDEh
80
chs_read_sectors2 = 7CD8h
81
chs_lookup_in_root_dir = 7D70h
82
chs_scan_for_filename = 7D4Eh
83
chs_err = 7CB1h
84
chs_noloader = 7CAEh
85
 
1132 Lrz 86
        push    ax cx           ; save our position on disk
87
        push    ss
88
        pop     es
1065 Lrz 89
; determine version of bootsector (LBA vs CHS)
1132 Lrz 90
;       mov     [read_sectors], chs_read_sectors
91
;       mov     [read_sectors2], chs_read_sectors2
92
;       mov     [lookup_in_root_dir], chs_lookup_in_root_dir
93
;       mov     [scan_for_filename], chs_scan_for_filename
94
;       mov     [err], chs_err
95
;       mov     [noloader], chs_noloader
96
        lea     di, [read_sectors]
97
        mov     si, chs_proc_addresses
98
        mov     cx, 6*2
99
        cmp     word [chs_scan_for_filename], 0xFF31    ; 'xor di,di'
100
        jz      @f
101
        add     si, cx
102
;       mov     [read_sectors], lba_read_sectors
103
;       mov     [read_sectors2], lba_read_sectors2
104
;       mov     [lookup_in_root_dir], lba_lookup_in_root_dir
105
;       mov     [scan_for_filename], lba_scan_for_filename
106
;       mov     [err], lba_err
107
;       mov     [noloader], lba_noloader
1065 Lrz 108
@@:
1132 Lrz 109
        rep     movsb
110
        mov     cl, [BPB_SecsPerClus]
111
        mov     [sect_per_clus], cx
112
        xor     bx, bx
1065 Lrz 113
; determine size of cache for folders
1132 Lrz 114
        int     12h             ; ax = size of available base memory in Kb
115
        sub     ax, 94000h / 1024
116
        jae     @f
1065 Lrz 117
nomem:
1132 Lrz 118
        mov     si, nomem_str
119
        jmp     [err_]
1065 Lrz 120
@@:
1132 Lrz 121
        shr     ax, 3
122
        mov     [cachelimit], ax        ; size of cache - 1
1065 Lrz 123
; get type of file system - FAT12 or FAT16?
124
; calculate number of clusters
1132 Lrz 125
        mov     ax, [BPB_TotSec16]
126
        xor     dx, dx
127
        test    ax, ax
128
        jnz     @f
129
        mov     ax, word [BPB_TotSec32]
130
        mov     dx, word [BPB_TotSec32+2]
1065 Lrz 131
@@:
1132 Lrz 132
        sub     ax, [bp-8]      ; dword [bp-8] = first data sector
133
        sbb     dx, [bp-6]
134
        jb      j_noloader
135
        div     [sect_per_clus]
1065 Lrz 136
; ax = number of clusters
137
; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes
1132 Lrz 138
        mov     [fat_type], ch
139
        cmp     ax, 0xFF5
140
        jb      init_fat12
141
        inc     [fat_type]
1065 Lrz 142
init_fat16:
143
; no sectors loaded
1132 Lrz 144
        mov     di, 0x8200
145
        xor     ax, ax
146
        mov     cx, 0x100/2
147
        rep     stosw
148
        jmp     init_fat_done
1065 Lrz 149
init_fat12:
150
; read FAT
1132 Lrz 151
        push    0x6000
152
        pop     es
153
        mov     ax, [BPB_RsvdSecCnt]
154
        mov     cx, [BPB_FATSz16]
155
        cmp     cx, 12
156
        jb      @f
157
        mov     cx, 12
1065 Lrz 158
@@:
1132 Lrz 159
        xor     dx, dx
160
        call    [read_sectors]
1065 Lrz 161
init_fat_done:
162
; if cluster = sector, we need to read second part of our file
163
; (bootsector loads only first cluster of kordldr.f1x)
1132 Lrz 164
        pop     cx ax           ; restore our position on disk
165
        cmp     cx, 1
166
        ja      kordldr_full
167
        sub     ax, [bp-8]
168
        inc     ax
169
        inc     ax              ; ax = first cluster of kordldr.f12
170
        call    get_next_cluster
171
        jc      @f
1065 Lrz 172
j_noloader:
1132 Lrz 173
        jmp     [noloader]
1065 Lrz 174
@@:
1132 Lrz 175
        dec     ax
176
        dec     ax
177
        push    0x800
178
        pop     es
179
        call    [read_sectors2]
1065 Lrz 180
kordldr_full:
181
; ...continue loading...
1132 Lrz 182
        mov     di, secondary_loader_info
183
        call    load_file
184
        test    bx, bx
185
        mov     bx, [err_]
186
        jz      @f
187
        mov     si, aKernelNotFound
188
        jmp     bx
1065 Lrz 189
@@:
190
; for subsequent calls to callback function, hook error handler
1132 Lrz 191
;       mov     byte [bx], 0xE9         ; 'jmp' opcode
192
;       mov     ax, hooked_err - 3
193
;       sub     ax, bx
194
;       mov     word [bx+1], ax
1065 Lrz 195
; push hooked_err / ret
1132 Lrz 196
        mov     word [bx], 0x68 + ((hooked_err and 0xFF) shl 8)
197
        mov     word [bx+2], (hooked_err shr 8) + (0xC3 shl 8)
1065 Lrz 198
; set registers for secondary loader
1132 Lrz 199
        mov     ah, [BS_DrvNum]
200
        mov     al, 'f'
201
        test    ah, ah
202
        jns     @f
203
        sub     ah, 80h
204
        mov     al, 'h'
1065 Lrz 205
@@:
1132 Lrz 206
        mov     bx, '12'
207
        cmp     [fat_type], 0
208
        jz      @f
209
        mov     bh, '6'
1065 Lrz 210
@@:
1132 Lrz 211
        mov     si, callback    ; ds:si = far pointer to callback procedure
212
        jmp     far [si-callback+secondary_loader_info] ; jump to 1000:0000
1065 Lrz 213
 
1132 Lrz 214
nomem_str       db      'No memory',0
1065 Lrz 215
 
216
chs_proc_addresses:
1132 Lrz 217
        dw      chs_read_sectors
218
        dw      chs_read_sectors2
219
        dw      chs_lookup_in_root_dir
220
        dw      chs_scan_for_filename
221
        dw      chs_err
222
        dw      chs_noloader
1065 Lrz 223
lba_proc_addresses:
1132 Lrz 224
        dw      lba_read_sectors
225
        dw      lba_read_sectors2
226
        dw      lba_lookup_in_root_dir
227
        dw      lba_scan_for_filename
228
        dw      lba_err
229
        dw      lba_noloader
1065 Lrz 230
 
231
get_next_cluster:
232
; in: ax = cluster
233
; out: if there is next cluster: CF=1, ax = next cluster
234
; out: if there is no next cluster: CF=0
1132 Lrz 235
        push    si
236
        cmp     [fat_type], 0
237
        jnz     gnc16
1065 Lrz 238
; for FAT12
1132 Lrz 239
        push    ds
240
        push    0x6000
241
        pop     ds
242
        mov     si, ax
243
        shr     si, 1
244
        add     si, ax
245
        test    al, 1
246
        lodsw
247
        jz      @f
248
        shr     ax, 4
1065 Lrz 249
@@:
1132 Lrz 250
        and     ax, 0xFFF
251
        cmp     ax, 0xFF7
252
        pop     ds si
253
        ret
1065 Lrz 254
; for FAT16
255
gnc16:
256
; each sector contains 200h bytes = 100h FAT entries
257
; so ah = # of sector, al = offset in sector
1132 Lrz 258
        mov     si, ax
259
        mov     ah, 0
260
        shr     si, 8
1065 Lrz 261
; calculate segment for this sector of FAT table
262
; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si)
263
; segment = 6000 + 20*si, offset = 0
1132 Lrz 264
        push    es
265
        push    si
266
        shl     si, 5
267
        add     si, 0x6000
268
        mov     es, si
269
        pop     si
270
        cmp     byte [ss:0x8200+si], ah ; sector already loaded?
271
        jnz     @f
1065 Lrz 272
; load corresponding sector
1132 Lrz 273
        pusha
274
        push    es
275
        xor     bx, bx
276
        mov     ax, [BPB_RsvdSecCnt]
277
        xor     dx, dx
278
        add     ax, si
279
        adc     dx, bx
280
        mov     cx, 1   ; read 1 sector
281
        call    [read_sectors]
282
        pop     es
283
        popa
1065 Lrz 284
@@:
1132 Lrz 285
        mov     si, ax
286
        add     si, si
287
;       mov     ax, [es:si]
288
        lods    word [es:si]
289
        pop     es
290
        cmp     ax, 0xFFF7
291
        pop     si
292
        ret
1065 Lrz 293
 
294
if $ > 0x8000
295
error 'get_next_cluster must fit in first sector of kordldr.f1x!'
296
end if
297
 
298
load_file:
299
; in: ss:bp = 0:7C00
300
; in: ds:di -> information structure
1132 Lrz 301
;       dw:dw   address
302
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
303
;       ASCIIZ  name
1065 Lrz 304
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found
305
; out: dx:ax = file size (0xFFFFFFFF if file not found)
1132 Lrz 306
        xor     ax, ax  ; start from root directory
307
        mov     dx, -1
308
        mov     word [filesize], dx
309
        mov     word [filesize+2], dx   ; initialize file size with invalid value
310
        lea     si, [di+6]
1065 Lrz 311
parse_dir_loop:
312
; convert name to FAT name
1132 Lrz 313
        push    di
314
        push    ax
315
        push    ss
316
        pop     es
1065 Lrz 317
; convert ASCIIZ filename to FAT name
1132 Lrz 318
        mov     di, filename
319
        push    di
320
        mov     cx, 8+3
321
        mov     al, ' '
322
        rep     stosb
323
        pop     di
324
        mov     cl, 8   ; 8 symbols per name
325
        mov     bl, 1
1065 Lrz 326
nameloop:
1132 Lrz 327
        lodsb
328
        test    al, al
329
        jz      namedone
330
        cmp     al, '/'
331
        jz      namedone
332
        cmp     al, '.'
333
        jz      namedot
334
        dec     cx
335
        js      badname
336
        cmp     al, 'a'
337
        jb      @f
338
        cmp     al, 'z'
339
        ja      @f
340
        sub     al, 'a'-'A'
1065 Lrz 341
@@:
1132 Lrz 342
        stosb
343
        jmp     nameloop
1065 Lrz 344
namedot:
1132 Lrz 345
        inc     bx
346
        jp      badname
347
        add     di, cx
348
        mov     cl, 3
349
        jmp     nameloop
350
badname:        ; do not make direct js/jp to notfound_pop:
351
                ; this generates long forms of conditional jumps and results in longer code
352
        jmp     notfound_pop
1065 Lrz 353
namedone:
354
; scan directory
1132 Lrz 355
        pop     ax      ; ax = cluster of directory or 0 for root
356
        push    ds
357
        push    si
358
        push    es
359
        pop     ds
360
        mov     si, filename    ; ds:si -> filename in FAT style
361
        test    ax, ax
362
        jnz     lookup_in_notroot_dir
1065 Lrz 363
; for root directory, use the subroutine from bootsector
1132 Lrz 364
        call    [lookup_in_root_dir]
365
        jmp     lookup_done
1065 Lrz 366
lookup_in_notroot_dir:
367
; for other directories, read a folder sector-by-sector and scan
368
; first, try to use the cache
1132 Lrz 369
        push    ds
370
        push    cs
371
        pop     ds
372
        mov     bx, [cachelimit]
373
        add     bx, bx
374
        mov     di, foldcache_mark
1065 Lrz 375
@@:
1132 Lrz 376
        mov     dx, [foldcache_clus+di-foldcache_mark+bx]
377
        cmp     dx, ax
378
        jz      cacheok
379
        test    dx, dx
380
        jz      cacheadd        ; the cache has place for new entry
381
        dec     bx
382
        dec     bx
383
        jns     @b
1065 Lrz 384
; the folder is not present in the cache, so add it
385
; the cache is full; find the oldest entry and replace it with the new one
1132 Lrz 386
        mov     dx, [cachelimit]
1065 Lrz 387
@@:
1132 Lrz 388
        inc     bx
389
        inc     bx
390
        cmp     word [di+bx], dx        ; marks have values 0 through [cachelimit]
391
        jnz     @b
1065 Lrz 392
cacheadd:
1132 Lrz 393
        or      word [di+bx], 0xFFFF    ; very big value, it will be changed soon
394
        mov     [foldcache_clus+di-foldcache_mark+bx], ax
395
        and     [foldcache_size+di-foldcache_mark+bx], 0        ; no folder items yet
1065 Lrz 396
cacheok:
397
; update cache marks
1132 Lrz 398
        mov     dx, [di+bx]
399
        mov     cx, [foldcache_size+di-foldcache_mark+bx]
400
        mov     di, [cachelimit]
401
        add     di, di
1065 Lrz 402
cacheupdate:
1132 Lrz 403
        cmp     [foldcache_mark+di], dx
404
        adc     [foldcache_mark+di], 0
405
        dec     di
406
        dec     di
407
        jns     cacheupdate
408
        and     [foldcache_mark+bx], 0
1065 Lrz 409
; done, bx contains (position in cache)*2
1132 Lrz 410
        pop     ds
411
;       mov     dx, bx
412
;       shl     dx, 8           ; dx = (position in cache)*0x2000/0x10
413
;       add     dx, 0x9200
414
        lea     dx, [bx+0x92]
415
        xchg    dl, dh
416
        mov     es, dx
417
        jcxz    not_in_cache
418
        call    [scan_for_filename]
419
        jz      lookup_done
1065 Lrz 420
not_in_cache:
421
; cache miss, read folder data from disk
1132 Lrz 422
        mov     bx, cx
423
        shr     bx, 4
424
        shl     cx, 5
425
        mov     di, cx          ; es:di -> free space in cache entry
1065 Lrz 426
; external loop: scan clusters
427
folder_next_cluster:
428
; internal loop: scan sectors in cluster
1132 Lrz 429
        mov     cx, [sect_per_clus]
430
        push    ax
431
        dec     ax
432
        dec     ax
433
        mul     cx
434
        add     ax, [bp-8]
435
        adc     dx, [bp-6]      ; dx:ax = absolute sector
1065 Lrz 436
folder_next_sector:
437
; skip first bx sectors
1132 Lrz 438
        dec     bx
439
        jns     folder_skip_sector
440
        push    cx
441
        push    es di
442
        push    0x8000
443
        pop     es
444
        xor     bx, bx
445
        mov     cx, 1
446
        push    es
447
        call    [read_sectors]
1065 Lrz 448
; copy data to the cache...
1132 Lrz 449
        pop     ds
450
        pop     di es
451
        cmp     di, 0x2000      ; ...if there is free space, of course
452
        jae     @f
453
        push    si di
454
        mov     cx, 0x100
455
        xor     si, si
456
        rep     movsw
457
        mov     di, es
458
        shr     di, 8
459
        add     [ss:foldcache_size+di-0x92], 0x10       ; 0x10 new entries in the cache
460
        pop     di si
1065 Lrz 461
@@:
1132 Lrz 462
        push    es
463
        push    0x8000
464
        pop     es
465
        push    cs
466
        pop     ds
467
        mov     cx, 0x10
468
        call    [scan_for_filename]
469
        pop     es
470
        pop     cx
471
        jz      lookup_done_pop
1065 Lrz 472
folder_skip_sector:
1132 Lrz 473
        inc     ax
474
        jnz     @f
475
        inc     dx
1065 Lrz 476
@@:
1132 Lrz 477
        loop    folder_next_sector
478
        pop     ax      ; ax = current cluster
479
        call    get_next_cluster
480
        jc      folder_next_cluster
481
        stc
482
        push    ax
1065 Lrz 483
lookup_done_pop:
1132 Lrz 484
        pop     ax
1065 Lrz 485
lookup_done:
1132 Lrz 486
        pop     si
487
        pop     ds
1065 Lrz 488
; CF=1 <=> failed
1132 Lrz 489
        jnc     found
1065 Lrz 490
notfound:
1132 Lrz 491
        pop     di
492
        mov     bx, 2   ; file not found
493
        mov     ax, 0xFFFF
494
        mov     dx, ax  ; invalid file size
495
        ret
1065 Lrz 496
notfound_pop:
1132 Lrz 497
        pop     ax
498
        jmp     notfound
1065 Lrz 499
found:
1132 Lrz 500
        mov     ax, [es:di+26]  ; get cluster
501
        test    byte [es:di+11], 10h    ; directory?
502
        jz      regular_file
503
        cmp     byte [si-1], 0
504
        jz      notfound        ; don't read directories as a regular files
1065 Lrz 505
; ok, we have found a directory and the caller requested a file into it
1132 Lrz 506
        pop     di
507
        jmp     parse_dir_loop  ; restart with new cluster in ax
1065 Lrz 508
regular_file:
1132 Lrz 509
        cmp     byte [si-1], 0
510
        jnz     notfound        ; file does not contain another files
1065 Lrz 511
; ok, we have found a regular file and the caller requested it
512
; save file size
1132 Lrz 513
        mov     dx, [es:di+28]
514
        mov     [filesize], dx
515
        mov     dx, [es:di+30]
516
        mov     [filesize+2], dx
517
        pop     di
518
        mov     si, [di+4]
519
        shl     si, 3
520
        push    si              ; [ds:di+4] = limit in 4K blocks
521
        les     bx, [di]        ; es:bx -> buffer
1065 Lrz 522
clusloop:
523
; ax = first cluster, top of stack contains limit in sectors
1132 Lrz 524
        mov     si, ax  ; remember current cluster
525
        xor     cx, cx  ; cx will contain number of consecutive clusters
526
        mov     word [cur_delta], cx
527
        mov     word [cur_delta+2], cx
528
        mov     di, ax
1065 Lrz 529
clusfind:
1132 Lrz 530
        inc     di
531
        inc     cx
532
        call    get_next_cluster
533
        jnc     clusread
534
        cmp     ax, di
535
        jz      clusfind
536
        stc
1065 Lrz 537
clusread:
1132 Lrz 538
        pop     di      ; limit in sectors
539
        push    ax      ; save next cluster
540
        pushf           ; save flags
1065 Lrz 541
; read cx clusters, starting from si
542
; calculate number of sectors
1132 Lrz 543
        xchg    ax, cx
544
        mul     [sect_per_clus]
1065 Lrz 545
; dx:ax = number of sectors; compare with limit
1132 Lrz 546
        mov     word [num_sectors], ax
547
        mov     word [num_sectors+2], dx
548
        jmp     @f
1065 Lrz 549
continue_load_file:
1132 Lrz 550
        les     bx, [di]        ; es:bx -> buffer
551
        mov     di, [di+4]      ; ds:di = limit in 4K blocks
552
        shl     di, 3   ; now di = limit in sectors
553
        mov     ax, word [num_sectors]
554
        mov     dx, word [num_sectors+2]
555
        mov     si, [cur_cluster]
556
        push    [next_cluster]
557
        push    [flags]
558
        or      ax, dx
559
        jz      nextclus
1065 Lrz 560
@@:
1132 Lrz 561
        test    dx, dx
562
        jnz     clusdecrease
563
        push    dx      ; limit was not exceeded
564
        cmp     ax, di
565
        jbe     @f
566
        pop     ax
1065 Lrz 567
clusdecrease:
1132 Lrz 568
        push    1       ; limit was exceeded
569
        mov     ax, di
1065 Lrz 570
@@:
1132 Lrz 571
        sub     di, ax  ; calculate new limit
572
        sub     word [num_sectors], ax
573
        sbb     word [num_sectors+2], 0
1065 Lrz 574
; calculate starting sector
1132 Lrz 575
        xchg    ax, cx
576
        lea     ax, [si-2]
577
        mul     [sect_per_clus]
578
        add     ax, word [cur_delta]
579
        adc     dx, word [cur_delta+2]
580
        add     word [cur_delta], cx
581
        adc     word [cur_delta+2], 0
1065 Lrz 582
; read
1132 Lrz 583
        call    [read_sectors2]
584
        pop     dx
1065 Lrz 585
; next cluster?
586
nextclus:
1132 Lrz 587
        popf
588
        pop     ax
589
        mov     [cur_cluster], si
590
        mov     [next_cluster], ax
591
        pushf
592
        pop     [flags]
593
        jnc     @f      ; no next cluster => return
594
        mov     dl, 1   ; dh=0 in any case
595
        test    di, di
596
        jz      @f      ; if there is next cluster but current limit is 0 => return: limit exceeded
597
        push    di
598
        jmp     clusloop        ; all is ok, continue
1065 Lrz 599
hooked_err:
1132 Lrz 600
        mov     sp, 7C00h-12-2  ; restore stack
601
        mov     dx, 3           ; return: read error
1065 Lrz 602
@@:
1132 Lrz 603
        mov     bx, dx
604
        mov     ax, [filesize]
605
        mov     dx, [filesize+2]
606
        ret
1065 Lrz 607
 
608
; Callback function for secondary loader
609
callback:
610
; in: ax = function number; only functions 1 and 2 are defined for now
611
; save caller's stack
1132 Lrz 612
        mov     dx, ss
613
        mov     cx, sp
1065 Lrz 614
; set our stack (required because we need ss=0)
1132 Lrz 615
        xor     si, si
616
        mov     ss, si
617
        mov     sp, 7C00h-8
618
        mov     bp, 7C00h
619
        push    dx
620
        push    cx
1065 Lrz 621
; call our function
1132 Lrz 622
        stc     ; unsupported function
623
        dec     ax
624
        jz      callback_readfile
625
        dec     ax
626
        jnz     callback_ret
1065 Lrz 627
; function 2: continue loading file
628
; can be called only after function 1 returned value bx=1 (only part of file was loaded)
629
; in: ds:di -> information structure
1132 Lrz 630
;       dw:dw   address
631
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
1065 Lrz 632
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error
633
; out: dx:ax = file size
1132 Lrz 634
        call    continue_load_file
635
        jmp     callback_ret_succ
1065 Lrz 636
callback_readfile:
637
; function 1: read file
638
; in: ds:di -> information structure
1132 Lrz 639
;       dw:dw   address
640
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
641
;       ASCIIZ  name
1065 Lrz 642
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error
643
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
1132 Lrz 644
        call    load_file
1065 Lrz 645
callback_ret_succ:
1132 Lrz 646
        clc     ; function is supported
1065 Lrz 647
callback_ret:
648
; restore caller's stack
1132 Lrz 649
        pop     cx
650
        pop     ss
651
        mov     sp, cx
1065 Lrz 652
; return to caller
1132 Lrz 653
        retf
1065 Lrz 654
 
655
secondary_loader_info:
1132 Lrz 656
        dw      0, 0x1000
657
        dw      0x30000 / 0x1000
658
        db      'kord/loader',0
659
aKernelNotFound db      'Fatal error: cannot load the secondary loader',0
1065 Lrz 660
 
1132 Lrz 661
foldcache_clus  dw      0,0,0,0,0,0,0   ; start with no folders in cache
662
foldcache_mark  rw      7
663
foldcache_size  rw      7
664
filename        rb      11
1065 Lrz 665
if $ > 0x8200
666
error: table overwritten
667
end if