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 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
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
170
        rep     movsw
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, ' '
313
        rep     stosb
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
437
        rep     movsw
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
594
        repz    cmps byte [ss:si], byte [es:di]
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