Subversion Repositories Kolibri OS

Rev

Rev 1635 | 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 FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here
29
; ss:bp = 0:7C00
30
; ds = 0
31
virtual at bp
1132 Lrz 32
                rb      3       ; BS_jmpBoot
33
                rb      8       ; BS_OEMName, ignored
34
                dw      ?       ; BPB_BytsPerSec
35
BPB_SecsPerClus db      ?
36
BPB_RsvdSecCnt  dw      ?
37
BPB_NumFATs     db      ?
38
BPB_RootEntCnt  dw      ?
39
                dw      ?       ; BPB_TotSec16
40
                db      ?       ; BPB_Media
41
                dw      ?       ; BPB_FATSz16 = 0 for FAT32
42
BPB_SecPerTrk   dw      ?
43
BPB_NumHeads    dw      ?
44
BPB_HiddSec     dd      ?
45
                dd      ?       ; BPB_TotSec32
46
BPB_FATSz32     dd      ?
47
BPB_ExtFlags    dw      ?
48
                dw      ?       ; BPB_FSVer
49
BPB_RootClus    dd      ?
1065 Lrz 50
filesize:
1132 Lrz 51
                dw      ?       ; BPB_FSInfo
52
                dw      ?       ; BPB_BkBootSec
53
                rb      12      ; BPB_Reserved
54
BS_DrvNum       db      ?
55
                db      ?       ; BS_Reserved1
56
                db      ?       ; BS_BootSig
57
                dd      ?       ; BS_VolID
58
;               rb      11      ; BS_VolLab
59
;               rb      5       ; BS_FilSysType, first 5 bytes
60
read_sectors32  dw      ?
61
read_sectors2   dw      ?
62
err_             dw      ?
63
noloader        dw      ?
64
cachelimit      dw      ?
65
fatcachehead    rw      2
66
fatcacheend     dw      ?
67
                rb      3       ; BS_FilSysType, last 3 bytes
68
curseg          dw      ?
69
num_sectors     dd      ?
70
cur_cluster     dd      ?
71
next_cluster    dd      ?
72
flags           dw      ?
73
cur_delta       dd      ?
1065 Lrz 74
end virtual
75
 
76
; procedures from boot sector
77
; LBA version
78
lba_read_sectors2 = 7CD6h
79
lba_err = 7CAAh
1132 Lrz 80
lba_noloader = 7CA7h    ; = lba_err - 3
1065 Lrz 81
; CHS version
82
chs_read_sectors2 = 7CD2h
83
chs_err = 7CA6h
1132 Lrz 84
chs_noloader = 7CA3h    ; = chs_err - 3
1065 Lrz 85
 
1132 Lrz 86
        push    eax cx          ; save our position on disk
1065 Lrz 87
; determine version of bootsector (LBA vs CHS)
1132 Lrz 88
        mov     [read_sectors2], chs_read_sectors2
89
        mov     bx, chs_err
90
        mov     [err_], bx
91
;       mov     [noloader], chs_noloader
92
        cmp     byte [bx], 0xE8         ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version
93
        jz      @f
94
        add     [read_sectors2], lba_read_sectors2 - chs_read_sectors2
95
        add     [err_], lba_err - chs_err
96
;       mov     [noloader], lba_noloader
1065 Lrz 97
@@:
1132 Lrz 98
        xor     bx, bx
1065 Lrz 99
; determine size of cache for folders
1132 Lrz 100
        int     12h             ; ax = size of available base memory in Kb
101
        sub     ax, 92000h / 1024
102
        jae     @f
1065 Lrz 103
nomem:
1132 Lrz 104
        mov     si, nomem_str
105
        jmp     [err_]
1065 Lrz 106
@@:
1132 Lrz 107
        shr     ax, 3
108
        mov     [cachelimit], ax        ; size of cache - 1
109
        mov     es, bx
1065 Lrz 110
; no folders in cache yet
1132 Lrz 111
        mov     di, foldcache_clus
112
        mov     cx, 8*4/2 + 1
113
        xor     ax, ax
3555 Serge 114
        rep stosw
1065 Lrz 115
; bootsector code caches one FAT sector, [bp-14], in 6000:0000
116
; initialize our (more advanced) FAT caching from this
1132 Lrz 117
        mov     di, 8400h
118
        mov     cx, di
119
        lea     si, [fatcachehead]
120
        mov     [si], si                ; no sectors in cache:
121
        mov     [si+2], si              ; 'prev' & 'next' links point to self
122
        mov     [fatcacheend], di       ; first free item = 8400h
123
        stosw                   ; 'next cached sector' link
124
        stosw                   ; 'prev cached sector' link
125
        mov     eax, [bp-14]
126
        stosd                           ; first sector number in cache
127
        test    eax, eax
128
        js      @f
129
        mov     [si], cx                ; 'first cached sector' link = 8400h
130
        mov     [si+2], cx              ; 'next cached sector' link = 8400h
131
        mov     [fatcacheend], di       ; first free item = 8406h
1065 Lrz 132
@@:
133
; if cluster = sector, we need to read second part of our file
134
; (bootsector loads only first cluster of kordldr.f32)
1132 Lrz 135
        pop     cx eax          ; restore our position on disk
136
        cmp     cx, 1
137
        ja      kordldr_full
138
        sub     eax, [bp-10]
139
        inc     eax
140
        inc     eax             ; eax = first cluster of kordldr.f32
141
        call    get_next_cluster
142
        jc      @f
143
;       jmp     [noloader]
144
        mov     ax, [err_]
145
        sub     ax, 3
146
        jmp     ax
1065 Lrz 147
@@:
1132 Lrz 148
        dec     eax
149
        dec     eax
150
        push    0x800
151
        pop     es
152
        call    [read_sectors2]
1065 Lrz 153
kordldr_full:
154
; bootsector code has read some data of root directory to 8000:0000
155
; initialize our folder caching from this
1132 Lrz 156
        mov     eax, [BPB_RootClus]
157
        mov     [foldcache_clus], eax
158
        mov     cx, [curseg]
159
        mov     ax, 8000h
160
        sub     cx, ax          ; cx = size of data read in paragraphs (0x10 bytes)
161
        shr     cx, 1           ; cx = size of folder data read in entries (0x20 bytes)
162
        mov     [foldcache_size], cx
163
        shl     cx, 4
164
        push    ds
165
        mov     ds, ax
166
        push    0x9000
167
        pop     es
168
        xor     si, si
169
        xor     di, di
3555 Serge 170
        rep movsw
1132 Lrz 171
        pop     ds
1065 Lrz 172
; ...continue loading...
1132 Lrz 173
        mov     di, secondary_loader_info
174
        call    load_file
175
        test    bx, bx
176
        mov     bx, [err_]
177
        jz      @f
178
        mov     si, aKernelNotFound
179
        jmp     bx
1065 Lrz 180
@@:
181
; for subsequent calls to callback function, hook error handler
182
; push hooked_err / ret
1132 Lrz 183
        mov     dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24)
1065 Lrz 184
; set registers for secondary loader
1132 Lrz 185
        mov     ah, [bp-2]              ; drive id
186
        mov     al, 'f'
187
        btr     ax, 15
188
        jnc     @f
189
        mov     al, 'h'
1065 Lrz 190
@@:
1132 Lrz 191
        mov     bx, '32'
192
        mov     si, callback
193
        jmp     far [si+secondary_loader_info-callback]
1065 Lrz 194
 
1132 Lrz 195
nomem_str       db      'No memory',0
1065 Lrz 196
 
197
cluster2sector:
1132 Lrz 198
        sub     eax, 2
1065 Lrz 199
clustersz2sectorsz:
1132 Lrz 200
        movzx   ecx, [BPB_SecsPerClus]
201
        mul     ecx
202
        ret
1065 Lrz 203
 
204
get_next_cluster:
205
; in: eax = cluster
206
; out: if there is next cluster: CF=1, eax = next cluster
207
; out: if there is no next cluster: CF=0
1132 Lrz 208
        push    di bx
209
        push    ds
210
        push    ss
211
        pop     ds
212
        push    ax
213
        shr     eax, 7
1065 Lrz 214
; eax = FAT sector number; look in cache
1132 Lrz 215
        mov     di, 8400h
1065 Lrz 216
.cache_lookup:
1132 Lrz 217
        cmp     di, [fatcacheend]
218
        jae     .not_in_cache
219
        scasd
220
        scasd
221
        jnz     .cache_lookup
1065 Lrz 222
.in_cache:
1132 Lrz 223
        sub     di, 8
1065 Lrz 224
; delete this sector from the list
1132 Lrz 225
        push    si
226
        mov     si, [di]
227
        mov     bx, [di+2]
228
        mov     [si+2], bx
229
        mov     [bx], si
230
        pop     si
231
        jmp     @f
1065 Lrz 232
.not_in_cache:
233
; cache miss
234
; cache is full?
1132 Lrz 235
        mov     di, [fatcacheend]
236
        cmp     di, 8C00h
237
        jnz     .cache_not_full
1065 Lrz 238
; yes, delete the oldest entry
1132 Lrz 239
        mov     di, [fatcachehead]
240
        mov     bx, [di]
241
        mov     [fatcachehead], bx
242
        push    word [di+2]
243
        pop     word [bx+2]
244
        jmp     .cache_append
1065 Lrz 245
.cache_not_full:
246
; no, allocate new sector
1132 Lrz 247
        add     [fatcacheend], 8
1065 Lrz 248
.cache_append:
249
; read FAT
1132 Lrz 250
        mov     [di+4], eax
251
        push    es
252
        pushad
253
        lea     cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))]        ; +0x10000 - for FASM
254
        shl     cx, 9-3
255
        mov     es, cx
256
        xor     bx, bx
257
        mov     cx, 1
258
        add     eax, [bp-6]     ; FAT start
259
        sub     eax, [bp-10]
260
        call    [read_sectors2]
261
        popad
262
        pop     es
1065 Lrz 263
@@:
264
; add new sector to the end of list
1132 Lrz 265
        mov     bx, di
266
        xchg    bx, [fatcachehead+2]
267
        push    word [bx]
268
        pop     word [di]
269
        mov     [bx], di
270
        mov     [di+2], bx
1065 Lrz 271
; get requested item
1132 Lrz 272
        lea     ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))]
273
        pop     di
274
        and     di, 0x7F
275
        shl     di, 2
276
        shl     ax, 9-3
277
        mov     ds, ax
278
        and     byte [di+3], 0x0F
279
        mov     eax, [di]
280
        pop     ds
281
        pop     bx di
282
        ;and    eax, 0x0FFFFFFF
283
        cmp     eax, 0x0FFFFFF7
284
        ret
1065 Lrz 285
 
286
if $ > 0x8000
287
error 'get_next_cluster must fit in first sector of kordldr.f32!'
288
end if
289
 
290
load_file:
291
; in: ss:bp = 0:7C00
292
; in: ds:di -> information structure
1132 Lrz 293
;       dw:dw   address
294
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
295
;       ASCIIZ  name
1065 Lrz 296
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found
297
; out: dx:ax = file size (0xFFFFFFFF if file not found)
1132 Lrz 298
        mov     eax, [BPB_RootClus]     ; start from root directory
299
        or      dword [filesize], -1    ; initialize file size with invalid value
300
        lea     si, [di+6]
1065 Lrz 301
parse_dir_loop:
302
; convert name to FAT name
1132 Lrz 303
        push    di
304
        push    ax
305
        push    ss
306
        pop     es
1065 Lrz 307
; convert ASCIIZ filename to FAT name
308
filename equ bp
1132 Lrz 309
        mov     di, filename
310
        push    di
311
        mov     cx, 8+3
312
        mov     al, ' '
3555 Serge 313
        rep stosb
1132 Lrz 314
        pop     di
315
        mov     cl, 8   ; 8 symbols per name
316
        mov     bl, 1
1065 Lrz 317
nameloop:
1132 Lrz 318
        lodsb
319
        test    al, al
320
        jz      namedone
321
        cmp     al, '/'
322
        jz      namedone
323
        cmp     al, '.'
324
        jz      namedot
325
        dec     cx
326
        js      badname
327
        cmp     al, 'a'
328
        jb      @f
329
        cmp     al, 'z'
330
        ja      @f
331
        sub     al, 'a'-'A'
1065 Lrz 332
@@:
1132 Lrz 333
        stosb
334
        jmp     nameloop
1065 Lrz 335
namedot:
1132 Lrz 336
        inc     bx
337
        jp      badname
338
        add     di, cx
339
        mov     cl, 3
340
        jmp     nameloop
341
badname:        ; do not make direct js/jp to notfound_pop:
342
                ; this generates long forms of conditional jumps and results in longer code
343
        jmp     notfound_pop
1065 Lrz 344
namedone:
345
; scan directory
1132 Lrz 346
        pop     ax      ; eax = cluster of directory
347
                        ; high word of eax is preserved by operations above
348
        push    ds
349
        push    si
1065 Lrz 350
; read a folder sector-by-sector and scan
351
; first, try to use the cache
1132 Lrz 352
        push    ss
353
        pop     ds
354
        mov     di, foldcache_mark
355
        xor     bx, bx
356
        mov     cx, [cachelimit]
1065 Lrz 357
@@:
1132 Lrz 358
        lea     si, [di+bx]
359
        mov     edx, dword [foldcache_clus+si-foldcache_mark+bx]
360
        cmp     edx, eax
361
        jz      cacheok
362
        test    edx, edx
363
        jz      cacheadd        ; the cache has place for new entry
364
        inc     bx
365
        inc     bx
366
        dec     cx
367
        jns     @b
1065 Lrz 368
; the folder is not present in the cache, so add it
369
; the cache is full; find the oldest entry and replace it with the new one
1132 Lrz 370
        mov     bx, -2
371
        mov     dx, [cachelimit]
1065 Lrz 372
@@:
1132 Lrz 373
        inc     bx
374
        inc     bx
375
        cmp     word [di+bx], dx        ; marks have values 0 through [cachelimit]
376
        jnz     @b
377
        lea     si, [di+bx]
1065 Lrz 378
cacheadd:
1132 Lrz 379
        or      word [di+bx], 0xFFFF    ; very big value, it will be changed soon
380
        and     [foldcache_size+di-foldcache_mark+bx], 0        ; no folder items yet
381
        mov     dword [foldcache_clus+si-foldcache_mark+bx], eax
1065 Lrz 382
cacheok:
383
; update cache marks
1132 Lrz 384
        mov     dx, [di+bx]
385
        mov     cx, [foldcache_size+di-foldcache_mark+bx]
386
        mov     di, [cachelimit]
387
        add     di, di
1065 Lrz 388
cacheupdate:
1132 Lrz 389
        cmp     [foldcache_mark+di], dx
390
        adc     [foldcache_mark+di], 0
391
        dec     di
392
        dec     di
393
        jns     cacheupdate
394
        and     [foldcache_mark+bx], 0
1065 Lrz 395
; done, bx contains (position in cache)*2
1132 Lrz 396
        ;mov    dx, bx
397
        ;shl    dx, 8           ; dx = (position in cache)*0x2000/0x10
398
        ;add    dx, 0x9000
399
        lea     dx, [bx + 0x90]
400
        xchg    dl, dh
401
        mov     ds, dx
402
        mov     si, filename    ; ss:si -> filename in FAT style
403
        call    scan_for_filename
404
        jz      lookup_done
1065 Lrz 405
; cache miss, read folder data from disk
1132 Lrz 406
        mov     bx, cx
407
        shr     bx, 4
408
        shl     cx, 5
409
        mov     di, cx          ; es:di -> free space in cache entry
1065 Lrz 410
; external loop: scan clusters
411
folder_next_cluster:
412
; internal loop: scan sectors in cluster
1132 Lrz 413
        push    eax
414
        call    cluster2sector
1065 Lrz 415
folder_next_sector:
416
; skip first bx sectors
1132 Lrz 417
        dec     bx
418
        jns     folder_skip_sector
419
        push    cx
420
        push    es di
421
        push    0x8000
422
        pop     es
423
        xor     bx, bx
424
        mov     cx, 1
425
        push    es
426
        push    eax
427
        call    [read_sectors2]
428
        pop     eax
1065 Lrz 429
; copy data to the cache...
1132 Lrz 430
        pop     ds
431
        pop     di es
432
        cmp     di, 0x2000      ; ...if there is free space, of course
433
        jae     @f
434
        pusha
435
        mov     cx, 0x100
436
        xor     si, si
3555 Serge 437
        rep movsw
1132 Lrz 438
        mov     di, es
439
        shr     di, 8
440
        add     [ss:foldcache_size+di-0x90], 0x10       ; 0x10 new entries in the cache
441
        popa
1065 Lrz 442
@@:
1132 Lrz 443
        push    es
444
        mov     cl, 0x10        ; ch=0 at this point
445
        call    scan_for_filename
446
        pop     es
447
        pop     cx
448
        jz      lookup_done_pop
1065 Lrz 449
folder_skip_sector:
1132 Lrz 450
        inc     eax
451
        loop    folder_next_sector
452
        pop     eax     ; eax = current cluster
453
        call    get_next_cluster
454
        jc      folder_next_cluster
455
        stc
456
        push    eax
1065 Lrz 457
lookup_done_pop:
1132 Lrz 458
        pop     eax
1065 Lrz 459
lookup_done:
1132 Lrz 460
        pop     si
1065 Lrz 461
; CF=1 <=> failed
1132 Lrz 462
        jnc     found
463
        pop     ds
1065 Lrz 464
notfound:
1132 Lrz 465
        pop     di
1065 Lrz 466
notfound2:
1132 Lrz 467
        mov     bx, 2   ; file not found
468
        mov     ax, 0xFFFF
469
        mov     dx, ax  ; invalid file size
470
        ret
1065 Lrz 471
notfound_pop:
1132 Lrz 472
        pop     ax
473
        jmp     notfound
1065 Lrz 474
found:
1132 Lrz 475
        mov     eax, [di+20-2]
476
        mov     edx, [di+28]
477
        mov     ax, [di+26]     ; get cluster
478
        test    byte [di+11], 10h       ; directory?
479
        pop     ds
480
        pop     di
481
        jz      regular_file
482
        cmp     byte [si-1], 0
483
        jz      notfound2       ; don't read directories as regular files
1065 Lrz 484
; ok, we have found a directory and the caller requested a file into it
1132 Lrz 485
        jmp     parse_dir_loop  ; restart with new cluster in ax
1065 Lrz 486
regular_file:
1132 Lrz 487
        cmp     byte [si-1], 0
488
        jnz     notfound2       ; file does not contain another files
1065 Lrz 489
; ok, we have found a regular file and the caller requested it
490
; save file size
1132 Lrz 491
        mov     [filesize], edx
492
        mov     si, [di+4]      ; [ds:di+4] = limit in 4K blocks
493
        shl     si, 3
494
        push    si
495
        les     bx, [di]        ; es:bx -> buffer
1065 Lrz 496
clusloop:
497
; eax = first cluster, top of stack contains limit in sectors
1132 Lrz 498
        mov     esi, eax        ; remember current cluster
499
        xor     ecx, ecx        ; ecx will contain number of consecutive clusters
500
        mov     [cur_delta], ecx
501
        mov     edi, eax
1065 Lrz 502
clusfind:
1132 Lrz 503
        inc     edi
504
        inc     ecx
505
        call    get_next_cluster
506
        jnc     clusread
507
        cmp     eax, edi
508
        jz      clusfind
509
        stc
1065 Lrz 510
clusread:
1132 Lrz 511
        pop     di      ; limit in sectors
512
        movzx   edi, di
513
        push    eax     ; save next cluster
514
        pushf           ; save flags
1065 Lrz 515
; read cx clusters, starting from si
516
; calculate number of sectors
1132 Lrz 517
        xchg    eax, ecx
518
        call    clustersz2sectorsz
519
        mov     [num_sectors], eax
520
        jmp     @f
1065 Lrz 521
continue_load_file:
1132 Lrz 522
        les     bx, [di]        ; es:bx -> buffer
523
        movzx   edi, word [di+4]        ; di = limit in 4K blocks
524
        shl     di, 3   ; now di = limit in sectors
525
        mov     eax, [num_sectors]
526
        mov     esi, [cur_cluster]
527
        push    [next_cluster]
528
        push    [flags]
529
        test    eax, eax
530
        jz      nextclus
1065 Lrz 531
@@:
532
; eax = number of sectors; compare with limit
1132 Lrz 533
        cmp     eax, edi
534
        seta    dl
535
        push    dx      ; limit was exceeded?
536
        jbe     @f
537
        mov     eax, edi
1065 Lrz 538
@@:
1132 Lrz 539
        sub     di, ax  ; calculate new limit
540
        sub     [num_sectors], eax
541
        mov     [cur_cluster], esi
1065 Lrz 542
; calculate starting sector
1132 Lrz 543
        push    ax
544
        xchg    eax, esi
545
        call    cluster2sector
546
        pop     cx
547
        add     eax, [cur_delta]
548
        add     [cur_delta], ecx
1065 Lrz 549
; read
1132 Lrz 550
        call    [read_sectors2]
551
        pop     dx
1065 Lrz 552
; next cluster?
553
nextclus:
1132 Lrz 554
        popf
555
        pop     eax
556
        mov     [next_cluster], eax
557
        pushf
558
        pop     [flags]
559
        jnc     @f      ; no next cluster => return
560
        mov     dl, 1   ; dh=0 in any case
561
        test    di, di
562
        jz      @f      ; if there is next cluster but current limit is 0 => return: limit exceeded
563
        push    di
564
        jmp     clusloop        ; all is ok, continue
1065 Lrz 565
hooked_err:
1132 Lrz 566
        mov     sp, 7C00h-14-2  ; restore stack
567
        mov     dx, 3           ; return: read error
1065 Lrz 568
@@:
1132 Lrz 569
        mov     bx, dx
570
        mov     ax, [filesize]
571
        mov     dx, [filesize+2]
572
        ret
1065 Lrz 573
 
574
scan_for_filename:
575
; in: ss:si -> 11-bytes FAT name
576
; in: ds:0 -> part of directory data
577
; in: cx = number of entries
578
; in: bh = 0
579
; out: if found: CF=0, ZF=1, es:di -> directory entry
580
; out: if not found, but continue required: CF=1 and ZF=0
581
; out: if not found and zero item reached: CF=1 and ZF=1
1132 Lrz 582
        push    ds
583
        pop     es
584
        xor     di, di
585
        push    cx
586
        jcxz    snoent
1065 Lrz 587
sloop:
1132 Lrz 588
        cmp     byte [di], bh
589
        jz      snotfound
590
        test    byte [di+11], 8         ; volume label?
591
        jnz     scont                   ; ignore volume labels
592
        pusha
593
        mov     cx, 11
3555 Serge 594
        repz cmps byte [ss:si], byte [es:di]
1132 Lrz 595
        popa
596
        jz      sdone
1065 Lrz 597
scont:
1132 Lrz 598
        add     di, 0x20
599
        loop    sloop
1065 Lrz 600
snoent:
1132 Lrz 601
        inc     cx      ; clear ZF flag
1065 Lrz 602
snotfound:
1132 Lrz 603
        stc
1065 Lrz 604
sdone:
1132 Lrz 605
        pop     cx
1065 Lrz 606
lrdret:
1132 Lrz 607
        ret
1065 Lrz 608
 
609
; Callback function for secondary loader
610
callback:
611
; in: ax = function number; only functions 1 and 2 are defined for now
612
; save caller's stack
1132 Lrz 613
        mov     dx, ss
614
        mov     cx, sp
1065 Lrz 615
; set our stack (required because we need ss=0)
1132 Lrz 616
        xor     si, si
617
        mov     ss, si
618
        mov     sp, 7C00h-10
619
        mov     bp, 7C00h
620
        push    dx
621
        push    cx
1065 Lrz 622
; call our function
1132 Lrz 623
        stc     ; unsupported function
624
        dec     ax
625
        jz      callback_readfile
626
        dec     ax
627
        jnz     callback_ret
1065 Lrz 628
; function 2: continue loading file
629
; can be called only after function 1 returned value bx=1 (only part of file was loaded)
630
; in: ds:di -> information structure
1132 Lrz 631
;       dw:dw   address
632
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
1065 Lrz 633
; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error
634
; out: dx:ax = file size
1132 Lrz 635
        call    continue_load_file
636
        jmp     callback_ret_succ
1065 Lrz 637
callback_readfile:
638
; function 1: read file
639
; in: ds:di -> information structure
1132 Lrz 640
;       dw:dw   address
641
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
642
;       ASCIIZ  name
1065 Lrz 643
; 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
644
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
1132 Lrz 645
        call    load_file
1065 Lrz 646
callback_ret_succ:
1132 Lrz 647
        clc     ; function is supported
1065 Lrz 648
callback_ret:
649
; restore caller's stack
1132 Lrz 650
        pop     cx
651
        pop     ss
652
        mov     sp, cx
1065 Lrz 653
; return to caller
1132 Lrz 654
        retf
1065 Lrz 655
 
656
secondary_loader_info:
1132 Lrz 657
        dw      0, 0x1000
658
        dw      0x30000 / 0x1000
659
        db      'kord/loader',0
660
aKernelNotFound db      'Fatal error: cannot load the secondary loader',0
1065 Lrz 661
 
662
;if $ > 0x8200
663
;error 'total size of kordldr.f32 must not exceed 1024 bytes!'
664
;end if
665
 
1132 Lrz 666
;foldcache_clus dd      0,0,0,0,0,0,0,0 ; start with no folders in cache
667
;foldcache_mark dw      0
668
;               rw      7
669
;foldcache_size rw      8
670
foldcache_clus  rd      8
671
foldcache_mark  rw      8
672
foldcache_size  rw      8