Subversion Repositories Kolibri OS

Rev

Rev 1065 | Rev 2288 | 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
        jmp     far 0:real_start
1065 Lrz 28
; special text
29
org $+0x7C00
30
real_start:
31
; initialize
1132 Lrz 32
        xor     ax, ax
33
        mov     ss, ax
34
        mov     sp, 0x7C00
35
        mov     ds, ax
36
        mov     es, ax
37
        cld
38
        sti
39
        mov     [bootdrive], dl
1065 Lrz 40
; check LBA support
1132 Lrz 41
        mov     ah, 41h
42
        mov     bx, 55AAh
43
        int     13h
44
        mov     si, aNoLBA
45
        jc      err_
46
        cmp     bx, 0AA55h
47
        jnz     err_
48
        test    cl, 1
49
        jz      err_
1065 Lrz 50
; get file system information
51
; scan for Primary Volume Descriptor
1132 Lrz 52
        db      66h
53
        push    10h-1
54
        pop     eax
1065 Lrz 55
pvd_scan_loop:
1132 Lrz 56
        mov     cx, 1
57
        inc     eax
58
        mov     bx, 0x1000
59
        call    read_sectors
60
        jnc     @f
1065 Lrz 61
fatal_read_err:
1132 Lrz 62
        mov     si, aReadError
63
err_:
64
        call    out_string
65
        mov     si, aPressAnyKey
66
        call    out_string
67
        xor     ax, ax
68
        int     16h
69
        int     18h
70
        jmp     $
1065 Lrz 71
@@:
1132 Lrz 72
        push    ds
73
        pop     es
74
        cmp     word [bx+1], 'CD'
75
        jnz     pvd_scan_loop
76
        cmp     word [bx+3], '00'
77
        jnz     pvd_scan_loop
78
        cmp     byte [bx+5], '1'
79
        jnz     pvd_scan_loop
1065 Lrz 80
; we have found ISO9660 descriptor, look for type
1132 Lrz 81
        cmp     byte [bx], 1    ; Primary Volume Descriptor?
82
        jz      pvd_found
83
        cmp     byte [bx], 0xFF ; Volume Descriptor Set Terminator?
84
        jnz     pvd_scan_loop
1065 Lrz 85
; Volume Descriptor Set Terminator reached, no PVD found - fatal error
1132 Lrz 86
        mov     si, no_pvd
87
        jmp     err_
1065 Lrz 88
pvd_found:
1132 Lrz 89
        add     bx, 80h
90
        mov     ax, [bx]
91
        mov     [lb_size], ax
1065 Lrz 92
; calculate number of logical blocks in one sector
1132 Lrz 93
        mov     ax, 800h
94
        cwd
95
        div     word [bx]
96
        mov     [lb_per_sec], ax
1065 Lrz 97
; get location of root directory
1132 Lrz 98
        mov     di, root_location
99
        movzx   eax, byte [bx+1Dh]
100
        add     eax, [bx+1Eh]
101
        stosd
1065 Lrz 102
; get memory size
1132 Lrz 103
        int     12h
104
        mov     si, nomem_str
105
        cmp     ax, 71000h / 400h
106
        jb      err_
107
        shr     ax, 1
108
        sub     ax, 60000h / 800h
109
        mov     [size_rest], ax
110
        mov     [free_ptr], 60000h / 800h
1065 Lrz 111
; load path table
112
; if size > 62K => it's very strange, avoid using it
113
; if size > (size of cache)/2 => avoid using it too
1132 Lrz 114
        mov     ecx, [bx+4]
115
        cmp     ecx, 0x10000 - 0x800
116
        ja      nopathtable
117
        shr     ax, 1
118
        cmp     ax, 0x20
119
        jae     @f
120
        shl     ax, 11
121
        cmp     cx, ax
122
        ja      nopathtable
1065 Lrz 123
@@:
124
; size is ok, try to load it
1132 Lrz 125
        mov     [pathtable_size], cx
126
        mov     eax, [bx+12]
127
        xor     edx, edx
128
        div     dword [lb_per_sec]
129
        imul    dx, [bx]
130
        mov     [pathtable_start], dx
131
        add     cx, dx
132
        call    cx_to_sectors
133
        xor     bx, bx
134
        push    6000h
135
        pop     es
136
        call    read_sectors
137
        jc      nopathtable
1065 Lrz 138
; path table has been loaded
1132 Lrz 139
        inc     [use_path_table]
140
        sub     [size_rest], cx
141
        add     [free_ptr], cx
1065 Lrz 142
nopathtable:
143
; init cache
1132 Lrz 144
        mov     ax, [size_rest]
145
        mov     [cache_size], ax
146
        mov     ax, [free_ptr]
147
        mov     [cache_start], ax
1065 Lrz 148
; load secondary loader
1132 Lrz 149
        mov     di, secondary_loader_info
150
        call    load_file
151
        test    bx, bx
152
        jnz     noloader
1065 Lrz 153
; set registers for secondary loader
1132 Lrz 154
        mov     ah, [bootdrive]
155
        mov     al, 'c'
156
        mov     bx, 'is'
157
        mov     si, callback
158
        jmp     far [si-callback+secondary_loader_info] ; jump to 1000:0000
1065 Lrz 159
 
160
noloader:
1132 Lrz 161
        mov     si, aKernelNotFound
162
        jmp     err_
1065 Lrz 163
 
164
read_sectors:
165
; es:bx = pointer to data
166
; eax = first sector
167
; cx = number of sectors
1132 Lrz 168
        pushad
169
        push    ds
1065 Lrz 170
do_read_sectors:
1132 Lrz 171
        push    ax
172
        push    cx
173
        cmp     cx, 0x7F
174
        jbe     @f
175
        mov     cx, 0x7F
1065 Lrz 176
@@:
177
; create disk address packet on the stack
178
; dq starting LBA
1132 Lrz 179
        db      66h
180
        push    0
181
        push    eax
1065 Lrz 182
; dd buffer
1132 Lrz 183
        push    es
184
        push    bx
1065 Lrz 185
; dw number of blocks to transfer (no more than 0x7F)
1132 Lrz 186
        push    cx
1065 Lrz 187
; dw packet size in bytes
1132 Lrz 188
        push    10h
1065 Lrz 189
; issue BIOS call
1132 Lrz 190
        push    ss
191
        pop     ds
192
        mov     si, sp
193
        mov     dl, [cs:bootdrive]
194
        mov     ah, 42h
195
        int     13h
196
        jc      diskreaderr
1065 Lrz 197
; restore stack
1132 Lrz 198
        add     sp, 10h
1065 Lrz 199
; increase current sector & buffer; decrease number of sectors
1132 Lrz 200
        movzx   esi, cx
201
        mov     ax, es
202
        shl     cx, 7
203
        add     ax, cx
204
        mov     es, ax
205
        pop     cx
206
        pop     ax
207
        add     eax, esi
208
        sub     cx, si
209
        jnz     do_read_sectors
210
        pop     ds
211
        popad
212
        ret
1065 Lrz 213
diskreaderr:
1132 Lrz 214
        add     sp, 10h + 2*2
215
        pop     ds
216
        popad
217
        stc
1065 Lrz 218
out_string.ret:
1132 Lrz 219
        ret
1065 Lrz 220
 
221
out_string:
222
; in: ds:si -> ASCIIZ string
1132 Lrz 223
        lodsb
224
        test    al, al
225
        jz      .ret
226
        mov     ah, 0Eh
227
        mov     bx, 7
228
        int     10h
229
        jmp     out_string
1065 Lrz 230
 
1132 Lrz 231
aNoLBA          db      'The drive does not support LBA!',0
232
aReadError      db      'Read error',0
233
no_pvd          db      'Primary Volume Descriptor not found!',0
234
nomem_str       db      'No memory',0
235
aPressAnyKey    db      13,10,'Press any key...',13,10,0
1065 Lrz 236
 
237
load_file:
238
; in: ds:di -> information structure
1132 Lrz 239
;       dw:dw   address
240
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
241
;       ASCIIZ  name
1065 Lrz 242
; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found
243
; out: dx:ax = file size (0xFFFFFFFF if file not found)
244
; parse path to the file
1132 Lrz 245
        lea     si, [di+6]
246
        mov     eax, [cs:root_location]
247
        cmp     [cs:use_path_table], 0
248
        jz      parse_dir
1065 Lrz 249
; scan for path in path table
1132 Lrz 250
        push    di
251
        push    6000h
252
        pop     es
253
        mov     di, [cs:pathtable_start]        ; es:di = pointer to current entry in path table
254
        mov     dx, 1   ; dx = number of current entry in path table, start from 1
255
        mov     cx, [cs:pathtable_size]
1065 Lrz 256
pathtable_newparent:
1132 Lrz 257
        mov     bx, dx  ; bx = number of current parent in path table: root = 1
1065 Lrz 258
scan_path_table_e:
1132 Lrz 259
        call    is_last_component
260
        jnc     path_table_scanned
1065 Lrz 261
scan_path_table_i:
1132 Lrz 262
        cmp     word [es:di+6], bx
263
        jb      .next
264
        ja      path_table_notfound
265
        call    test_filename1
266
        jc      .next
1065 Lrz 267
@@:
1132 Lrz 268
        lodsb
269
        cmp     al, '/'
270
        jnz     @b
271
        jmp     pathtable_newparent
1065 Lrz 272
.next:
273
; go to next entry
1132 Lrz 274
        inc     dx
275
        movzx   ax, byte [es:di]
276
        add     ax, 8+1
277
        and     al, not 1
278
        add     di, ax
279
        sub     cx, ax
280
        ja      scan_path_table_i
1065 Lrz 281
path_table_notfound:
1132 Lrz 282
        pop     di
283
        mov     ax, -1
284
        mov     dx, ax
285
        mov     bx, 2   ; file not found
286
        ret
1065 Lrz 287
path_table_scanned:
1132 Lrz 288
        movzx   eax, byte [es:di+1]
289
        add     eax, [es:di+2]
290
        pop     di
1065 Lrz 291
parse_dir:
292
; eax = logical block, ds:di -> information structure, ds:si -> file name
293
; was the folder already read?
1132 Lrz 294
        push    di ds
295
        push    cs
296
        pop     ds
297
        mov     [cur_desc_end], 2000h
298
        mov     bx, cachelist
1065 Lrz 299
.scan1:
1132 Lrz 300
        mov     bx, [bx+2]
301
        cmp     bx, cachelist
302
        jz      .notfound
303
        cmp     [bx+4], eax
304
        jnz     .scan1
1065 Lrz 305
.found:
306
; yes; delete this item from the list (the following code will append this item to the tail)
1132 Lrz 307
        mov     di, [bx]
308
        push    word [bx+2]
309
        pop     word [di+2]
310
        mov     di, [bx+2]
311
        push    word [bx]
312
        pop     word [di]
313
        mov     di, bx
314
        jmp     .scan
1065 Lrz 315
.notfound:
316
; no; load first sector of the folder to get its size
1132 Lrz 317
        push    eax
318
        push    si
319
        mov     si, 1
320
        call    load_phys_sector_for_lb_force
321
        mov     bx, si
322
        pop     si
323
        pop     eax
324
        jnc     @f
1065 Lrz 325
; read error - return
326
.readerr:
1132 Lrz 327
        pop     ds
1065 Lrz 328
.readerr2:
1132 Lrz 329
        pop     di
330
        mov     ax, -1
331
        mov     dx, ax
332
        mov     bx, 3
333
        ret
1065 Lrz 334
@@:
335
; first item of the folder describes the folder itself
336
; do not cache too big folders: size < 64K and size <= (total cache size)/2
1132 Lrz 337
        cmp     word [bx+12], 0
338
        jnz     .nocache
339
        mov     cx, [cache_size]        ; cx = cache size in sectors
340
        shr     cx, 1                   ; cx = (cache size)/2
341
        cmp     cx, 0x20
342
        jae     @f
343
        shl     cx, 11
344
        cmp     [bx+10], cx
345
        ja      .nocache
1065 Lrz 346
@@:
347
; we want to cache this folder; get space for it
1132 Lrz 348
        mov     cx, [bx+10]
349
        call    cx_to_sectors
350
        jnz     .yescache
1065 Lrz 351
.nocache:
1132 Lrz 352
        push    dword [bx+10]
353
        pop     dword [cur_nocache_len]
354
        call    lb_to_sector
355
        push    ds
356
        pop     es
357
        pop     ds
1065 Lrz 358
.nocache_loop:
1132 Lrz 359
        push    eax
360
        mov     dx, 1800h
361
        call    scan_for_filename_in_sector
362
        mov     cx, dx
363
        pop     eax
364
        jnc     .j_scandone
365
        sub     cx, bx
366
        sub     word [es:cur_nocache_len], cx
367
        sbb     word [es:cur_nocache_len+2], 0
368
        jb      .j_scandone
369
        ja      @f
370
        cmp     word [es:cur_nocache_len], 0
371
        jz      .j_scandone
1065 Lrz 372
@@:
1132 Lrz 373
        mov     cx, 1
374
        inc     eax
375
        push    es
376
        mov     bx, 1000h
377
        call    read_sectors
378
        pop     es
379
        jc      .readerr2
380
        jmp     .nocache_loop
1065 Lrz 381
.j_scandone:
1132 Lrz 382
        jmp     .scandone
1065 Lrz 383
.yescache:
1132 Lrz 384
        push    bx
385
        mov     bx, [cachelist.head]
1065 Lrz 386
.freeloop:
1132 Lrz 387
        cmp     cx, [size_rest]
388
        jbe     .sizeok
1065 Lrz 389
@@:
390
; if we are here: there is not enough free space, so we must delete old folders' data
391
; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2).
392
; one loop iteration: delete data of one folder
1132 Lrz 393
        pusha
394
        mov     dx, [bx+10]
395
        mov     es, dx          ; es = segment of folder data to be deleted
396
        xor     di, di
397
        mov     ax, [bx+8]
398
        add     ax, 0x7FF
399
        rcr     ax, 1
400
        shr     ax, 10
401
        push    ax
402
        shl     ax, 11-4        ; get number of paragraphs in folder data to be deleted
403
        mov     cx, [cache_size]
404
        add     cx, [cache_start]
405
        push    ds
406
        push    ax
407
        add     ax, dx
408
        mov     ds, ax
409
        pop     ax
410
        shl     cx, 11-4
411
        sub     cx, dx          ; cx = number of paragraphs to be moved
412
        push    si
413
        xor     si, si
1065 Lrz 414
; move cx paragraphs from ds:si to es:di to get free space in the end of cache
415
@@:
1132 Lrz 416
        sub     cx, 1000h
417
        jbe     @f
418
        push    cx
419
        mov     cx, 8000h
420
        rep     movsw
421
        mov     cx, ds
422
        add     cx, 1000h
423
        mov     ds, cx
424
        mov     cx, es
425
        add     cx, 1000h
426
        mov     es, cx
427
        pop     cx
428
        jmp     @b
1065 Lrz 429
@@:
1132 Lrz 430
        add     cx, 1000h
431
        shl     cx, 3
432
        rep     movsw
433
        pop     si
434
        pop     ds
1065 Lrz 435
; correct positions in cache for existing items
1132 Lrz 436
        mov     cx, 80h
437
        mov     di, 8400h
1065 Lrz 438
.correct:
1132 Lrz 439
        cmp     [di+10], dx
440
        jbe     @f
441
        sub     [di+10], ax
1065 Lrz 442
@@:
1132 Lrz 443
        add     di, 12
444
        loop    .correct
1065 Lrz 445
; some additional space is free now
1132 Lrz 446
        pop     ax
447
        add     [size_rest], ax
448
        sub     [free_ptr], ax
1065 Lrz 449
; add cache item to the list of free items
1132 Lrz 450
        mov     dx, [bx]
451
        mov     ax, [free_cache_item]
452
        mov     [bx], ax
453
        mov     [free_cache_item], bx
454
        mov     bx, dx
1065 Lrz 455
; current iteration done
1132 Lrz 456
        popa
457
        jmp     .freeloop
1065 Lrz 458
.sizeok:
1132 Lrz 459
        mov     [cachelist.head], bx
460
        mov     word [bx+2], cachelist
1065 Lrz 461
; allocate new item in cache
1132 Lrz 462
        mov     di, [free_cache_item]
463
        test    di, di
464
        jz      .nofree
465
        push    word [di]
466
        pop     [free_cache_item]
467
        jmp     @f
1065 Lrz 468
.nofree:
1132 Lrz 469
        mov     di, [last_cache_item]
470
        add     [last_cache_item], 12
1065 Lrz 471
@@:
1132 Lrz 472
        pop     bx
473
        push    si di
474
;       mov     [di+4], eax     ; start of folder
475
        scasd
476
        stosd
477
        push    ax
478
        mov     ax, [free_ptr]
479
        shl     ax, 11-4
480
        mov     [di+10-8], ax
481
        mov     es, ax
482
        pop     ax
483
        add     [free_ptr], cx
484
        sub     [size_rest], cx
1065 Lrz 485
; read folder data
486
; first sector is already in memory, 0000:bx
1132 Lrz 487
        pusha
488
        mov     cx, [bx+10]
489
        mov     [di+8-8], cx    ; folder size in bytes
490
        mov     si, bx
491
        xor     di, di
492
        mov     cx, 0x1800
493
        sub     cx, si
494
        rep     movsb
495
        pop     ax
496
        push    di
497
        popa
1065 Lrz 498
; read rest of folder
1132 Lrz 499
        mov     esi, dword [lb_per_sec]
500
        add     eax, esi
501
        dec     si
502
        not     si
503
        and     ax, si
504
        mov     si, word [bx+10]
505
        mov     bx, di
506
        pop     di
507
        sub     si, bx
508
        jbe     @f
509
        mov     [cur_limit], esi
510
        call    read_many_bytes
511
        pop     si
512
        jnc     .scan
513
        jmp     .readerr
1065 Lrz 514
@@:
1132 Lrz 515
        pop     si
1065 Lrz 516
.scan:
517
; now we have required cache item; append it to the end of list
1132 Lrz 518
        mov     bx, [cachelist.tail]
519
        mov     [cachelist.tail], di
520
        mov     [di+2], bx
521
        mov     word [di], cachelist
522
        mov     [bx], di
1065 Lrz 523
; scan for given filename
1132 Lrz 524
        mov     es, [di+10]
525
        mov     dx, [di+8]
526
        pop     ds
527
        xor     bx, bx
528
        call    scan_for_filename_in_sector
1065 Lrz 529
.scandone:
1132 Lrz 530
        push    cs
531
        pop     es
532
        mov     bx, 2000h
533
        cmp     bx, [es:cur_desc_end]
534
        jnz     filefound
1065 Lrz 535
j_notfound:
1132 Lrz 536
        jmp     path_table_notfound
1065 Lrz 537
filefound:
538
@@:
1132 Lrz 539
        lodsb
540
        test    al, al
541
        jz      @f
542
        cmp     al, '/'
543
        jnz     @b
1065 Lrz 544
@@:
1132 Lrz 545
        mov     cl, [es:bx+8]
546
        test    al, al
547
        jz      @f
1065 Lrz 548
; parse next component of file name
1132 Lrz 549
        test    cl, 2   ; directory?
550
        jz      j_notfound
551
        mov     eax, [es:bx]
552
        pop     di
553
        jmp     parse_dir
1065 Lrz 554
@@:
1132 Lrz 555
        test    cl, 2   ; directory?
556
        jnz     j_notfound      ; do not allow read directories as regular files
1065 Lrz 557
; ok, now load the file
1132 Lrz 558
        pop     di
559
        les     bx, [di]
560
        call    normalize
561
        movzx   esi, word [di+4]        ; esi = limit in 4K blocks
562
        shl     esi, 12         ; esi = limit in bytes
563
        push    cs
564
        pop     ds
565
        mov     [cur_limit], esi
566
        mov     di, 2000h
1065 Lrz 567
loadloop:
1132 Lrz 568
        and     [cur_start], 0
1065 Lrz 569
.loadnew:
1132 Lrz 570
        mov     esi, [cur_limit]
571
        mov     eax, [cur_start]
572
        add     esi, eax
573
        mov     [overflow], 1
574
        sub     esi, [di+4]
575
        jb      @f
576
        xor     esi, esi
577
        dec     [overflow]
1065 Lrz 578
@@:
1132 Lrz 579
        add     esi, [di+4]     ; esi = number of bytes to read
580
        mov     [cur_start], esi
581
        sub     esi, eax
582
        jz      .loadcontinue
583
        xor     edx, edx
584
        div     dword [lb_size] ; eax = number of logical blocks to skip,
585
        mov     [first_byte], dx; [first_byte] = number of bytes to skip in 1st block
586
        cmp     byte [di+10], 0
587
        jnz     .interleaved
588
        add     eax, [di]
1065 Lrz 589
; read esi bytes from logical block eax to buffer es:bx
1132 Lrz 590
        call    read_many_bytes.with_first
591
        jc      .readerr3
1065 Lrz 592
.loadcontinue:
1132 Lrz 593
        mov     [cur_chunk], di
594
        add     di, 11
595
        cmp     di, [cur_desc_end]
596
        jae     @f
597
        cmp     [cur_limit], 0
598
        jnz     loadloop
1065 Lrz 599
@@:
1132 Lrz 600
        mov     bx, [overflow]
1065 Lrz 601
.calclen:
602
; calculate length of file
1132 Lrz 603
        xor     ax, ax
604
        xor     dx, dx
605
        mov     di, 2000h
1065 Lrz 606
@@:
1132 Lrz 607
        add     ax, [di+4]
608
        adc     dx, [di+6]
609
        add     di, 11
610
        cmp     di, [cur_desc_end]
611
        jb      @b
612
        ret
1065 Lrz 613
.interleaved:
1132 Lrz 614
        mov     [cur_unit_limit], esi
615
        push    esi
1065 Lrz 616
; skip first blocks
1132 Lrz 617
        movzx   ecx, byte [di+9]        ; Unit Size
618
        movzx   esi, byte [di+10]       ; Interleave Gap
619
        add     si, cx
620
        mov     edx, [di]
1065 Lrz 621
@@:
1132 Lrz 622
        sub     eax, ecx
623
        jb      @f
624
        add     edx, esi
625
        jmp     @b
1065 Lrz 626
@@:
1132 Lrz 627
        add     ecx, eax        ; ecx = number of logical blocks to skip
628
        lea     eax, [ecx+edx]  ; eax = first logical block
629
        pop     esi
1065 Lrz 630
.interleaved_loop:
631
; get number of bytes in current file unit
1132 Lrz 632
        push    eax
633
        movzx   eax, byte [di+9]
634
        sub     ax, cx
635
        imul    eax, dword [lb_size]
636
        cmp     eax, esi
637
        ja      .i2
1065 Lrz 638
.i1:
1132 Lrz 639
        xchg    esi, eax
1065 Lrz 640
.i2:
1132 Lrz 641
        pop     eax
642
        sub     [cur_unit_limit], esi
643
        push    eax
1065 Lrz 644
; read esi bytes from logical block eax to buffer es:bx
1132 Lrz 645
        call    read_many_bytes.with_first
646
        pop     eax
647
        jnc     @f
1065 Lrz 648
.readerr3:
1132 Lrz 649
        mov     bx, 3
650
        jmp     .calclen
1065 Lrz 651
@@:
1132 Lrz 652
        mov     esi, [cur_unit_limit]
653
        test    esi, esi
654
        jz      .loadcontinue
655
        movzx   ecx, byte [di+9]        ; add Unit Size
656
        add     cl, byte [di+10]        ; add Interleave Gap
657
        adc     ch, 0
658
        add     eax, ecx
659
        xor     cx, cx
660
        mov     [first_byte], cx
661
        jmp     .interleaved_loop
1065 Lrz 662
 
663
cx_to_sectors:
1132 Lrz 664
        add     cx, 7FFh
665
        rcr     cx, 1
666
        shr     cx, 10
667
        ret
1065 Lrz 668
 
669
is_last_component:
670
; in: ds:si -> name
671
; out: CF set <=> current component is not last (=> folder)
1132 Lrz 672
        push    si
1065 Lrz 673
@@:
1132 Lrz 674
        lodsb
675
        test    al, al
676
        jz      @f
677
        cmp     al, '/'
678
        jnz     @b
679
        stc
1065 Lrz 680
@@:
1132 Lrz 681
        pop     si
682
        ret
1065 Lrz 683
 
684
test_filename1:
685
; in: ds:si -> filename, es:di -> path table item
686
; out: CF set <=> no match
1132 Lrz 687
        pusha
688
        mov     cl, [es:di]
689
        add     di, 8
690
        jmp     test_filename2.start
1065 Lrz 691
test_filename2:
692
; in: ds:si -> filename, es:bx -> directory item
693
; out: CF set <=> no match
1132 Lrz 694
        pusha
695
        mov     cl, [es:bx+32]
696
        lea     di, [bx+33]
1065 Lrz 697
.start:
1132 Lrz 698
        mov     ch, 0
1065 Lrz 699
@@:
1132 Lrz 700
        lodsb
701
        test    al, al
702
        jz      .test1
703
        cmp     al, '/'
704
        jz      .test1
705
        call    toupper
706
        mov     ah, al
707
        mov     al, [es:di]
708
        call    toupper
709
        inc     di
710
        cmp     al, ah
711
        loopz   @b
712
        jnz     .next1
1065 Lrz 713
; if we have reached this point: current name is done
1132 Lrz 714
        lodsb
715
        test    al, al
716
        jz      .ret
717
        cmp     al, '/'
718
        jz      .ret
1065 Lrz 719
; if we have reached this point: current name is done, but input name continues
720
; so they do not match
1132 Lrz 721
        jmp     .next1
1065 Lrz 722
.test1:
723
; if we have reached this point: input name is done, but current name continues
724
; "filename.ext;version" in ISO-9660 represents file "filename.ext"
725
; "filename." and "filename.;version" are also possible for "filename"
1132 Lrz 726
        cmp     byte [es:di], '.'
727
        jnz     @f
728
        inc     di
729
        dec     cx
730
        jz      .ret
1065 Lrz 731
@@:
1132 Lrz 732
        cmp     byte [es:di], ';'
733
        jnz     .next1
734
        jmp     .ret
1065 Lrz 735
.next1:
1132 Lrz 736
        stc
1065 Lrz 737
.ret:
1132 Lrz 738
        popa
739
        ret
1065 Lrz 740
 
741
toupper:
742
; in: al=symbol
743
; out: al=symbol in uppercase
1132 Lrz 744
        cmp     al, 'a'
745
        jb      .ret
746
        cmp     al, 'z'
747
        ja      .ret
748
        sub     al, 'a'-'A'
1065 Lrz 749
.ret:
1132 Lrz 750
        ret
1065 Lrz 751
 
752
scan_for_filename_in_sector:
753
; in: ds:si->filename, es:bx->folder data, dx=limit
754
; out: CF=0 if found
1132 Lrz 755
        push    bx
1065 Lrz 756
.loope:
1132 Lrz 757
        push    bx
1065 Lrz 758
.loop:
1132 Lrz 759
        cmp     bx, dx
760
        jae     .notfound
761
        cmp     byte [es:bx], 0
762
        jz      .loopd
763
        test    byte [es:bx+25], 4      ; ignore files with Associated bit
764
        jnz     .next
765
        call    test_filename2
766
        jc      .next
767
        push    ds es di
768
        push    es
769
        pop     ds
770
        push    cs
771
        pop     es
772
        mov     di, [es:cur_desc_end]
773
        movzx   eax, byte [bx+1]
774
        add     eax, [bx+2]
775
        stosd   ; first logical block
776
        mov     eax, [bx+10]
777
        stosd   ; length
778
        mov     al, [bx+25]
779
        stosb   ; flags
780
        mov     ax, [bx+26]
781
        stosw   ; File Unit size, Interleave Gap size
782
        mov     [es:cur_desc_end], di
783
        cmp     di, 3000h
784
        pop     di es ds
785
        jae     .done
786
        test    byte [es:bx+25], 80h
787
        jz      .done
1065 Lrz 788
.next:
1132 Lrz 789
        add     bl, [es:bx]
790
        adc     bh, 0
791
        jmp     .loop
1065 Lrz 792
.loopd:
1132 Lrz 793
        mov     ax, bx
794
        pop     bx
1065 Lrz 795
@@:
1132 Lrz 796
        add     bx, [cs:lb_size]
797
        jz      .done2
798
        cmp     bx, ax
799
        jb      @b
800
        jmp     .loope
1065 Lrz 801
.notfound:
1132 Lrz 802
        stc
1065 Lrz 803
.done:
1132 Lrz 804
        pop     bx
1065 Lrz 805
.done2:
1132 Lrz 806
        pop     bx
807
        ret
1065 Lrz 808
 
809
lb_to_sector:
1132 Lrz 810
        xor     edx, edx
811
        div     dword [lb_per_sec]
812
        ret
1065 Lrz 813
 
814
load_phys_sector_for_lb_force:
815
; in: eax = logical block, ds=0
816
; in: si=0 - accept 0 logical blocks, otherwise force read at least 1
817
; out: 0000:1000 = physical sector data; si -> logical block
818
; out: eax = next physical sector
819
; out: CF=1 if read error
820
; destroys cx
821
; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector
1132 Lrz 822
        call    lb_to_sector
823
        or      si, dx
824
        jnz     @f
825
        mov     si, 1800h
826
        jmp     .done
1065 Lrz 827
@@:
1132 Lrz 828
        mov     si, 1000h
829
        imul    dx, [lb_size]
830
        add     si, dx
831
        mov     cx, 1
832
        push    es bx
833
        push    ds
834
        pop     es
835
        mov     bx, 1000h
836
        call    read_sectors
837
        pop     bx es
838
        inc     eax
1065 Lrz 839
.done:
1132 Lrz 840
        ret
1065 Lrz 841
 
842
normalize:
843
; in: es:bx = far pointer
844
; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10)
1132 Lrz 845
        push    ax bx
846
        mov     ax, es
847
        shr     bx, 4
848
        add     ax, bx
849
        mov     es, ax
850
        pop     bx ax
851
        and     bx, 0x0F
852
        ret
1065 Lrz 853
 
854
read_many_bytes:
1132 Lrz 855
        and     [first_byte], 0
1065 Lrz 856
read_many_bytes.with_first:
857
; read esi bytes from logical block dx:ax to buffer es:bx
858
; out: CF=1 <=> disk error
1132 Lrz 859
        push    di
1065 Lrz 860
; load first physical sector
1132 Lrz 861
        push    bx si
862
        mov     si, [first_byte]
863
        call    load_phys_sector_for_lb_force
864
        jnc     @f
865
        pop     si bx
1065 Lrz 866
.ret:
1132 Lrz 867
        pop     di
868
        ret
1065 Lrz 869
@@:
1132 Lrz 870
        add     si, [first_byte]
871
        mov     ecx, 1800h
872
        sub     cx, si
873
        mov     ebx, esi
874
        pop     bx
875
        sub     ebx, ecx
876
        jnc     @f
877
        add     cx, bx
878
        xor     ebx, ebx
1065 Lrz 879
@@:
1132 Lrz 880
        pop     di
881
        sub     [cur_limit], ecx
882
        rep     movsb
883
        mov     esi, ebx
884
        mov     bx, di
885
        call    normalize
1065 Lrz 886
; load other physical sectors
887
; read esi bytes from physical sector eax to buffer es:bx
1132 Lrz 888
        test    esi, esi
889
        jz      .ret
890
        push    esi
891
        add     esi, 0x7FF
892
        and     si, not 0x7FF
893
        cmp     esi, [cur_limit]
894
        jbe     .okplace
1065 Lrz 895
.noplace:
1132 Lrz 896
        sub     esi, 800h
1065 Lrz 897
.okplace:
1132 Lrz 898
        shr     esi, 11 ; si = number of sectors
899
        mov     cx, si
900
        jz      @f
901
        call    read_sectors
1065 Lrz 902
@@:
1132 Lrz 903
        pop     esi
904
        jc      .ret
905
        movzx   ecx, cx
906
        add     eax, ecx
907
        shl     ecx, 11
908
        sub     [cur_limit], ecx
909
        sub     esi, ecx
910
        jc      .big
911
        jz      .nopost
912
        push    bx es
913
        push    ds
914
        pop     es
915
        mov     bx, 1000h
916
        mov     cx, 1
917
        call    read_sectors
918
        pop     es di
919
        jc      .ret2
920
        mov     cx, si
921
        mov     si, 1000h
922
        sub     word [cur_limit], cx
923
        sbb     word [cur_limit+2], 0
924
        rep     movsb
925
        mov     bx, di
926
        call    normalize
1065 Lrz 927
.nopost:
1132 Lrz 928
        clc
1065 Lrz 929
.ret2:
1132 Lrz 930
        pop     di
931
        ret
1065 Lrz 932
.big:
1132 Lrz 933
        mov     ax, es
934
        sub     ax, 80h
935
        mov     es, ax
936
        add     bx, 800h
937
        add     bx, si
938
        call    normalize
939
        sub     [cur_limit], esi
940
        jmp     .nopost
1065 Lrz 941
 
942
; Callback function for secondary loader
943
callback:
944
; in: ax = function number; only function 1 is defined for now
1132 Lrz 945
        dec     ax
946
        jz      callback_readfile
947
        dec     ax
948
        jz      callback_continueread
949
        stc     ; unsupported function
950
        retf
1065 Lrz 951
 
952
callback_readfile:
953
; function 1: read file
954
; in: ds:di -> information structure
1132 Lrz 955
;       dw:dw   address
956
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
957
;       ASCIIZ  name
1065 Lrz 958
; 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
959
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
1132 Lrz 960
        call    load_file
961
        clc     ; function is supported
962
        retf
1065 Lrz 963
 
964
callback_continueread:
965
; function 2: continue to read file
966
; in: ds:di -> information structure
1132 Lrz 967
;       dw:dw   address
968
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
1065 Lrz 969
; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error
970
; out: dx:ax = file size
1132 Lrz 971
        les     bx, [di]
972
        call    normalize
973
        movzx   esi, word [di+4]        ; si = limit in 4K blocks
974
        shl     esi, 12                 ; bp:si = limit in bytes
975
        push    cs
976
        pop     ds
977
        mov     [cur_limit], esi
978
        mov     di, [cur_chunk]
979
        call    loadloop.loadnew
980
        clc     ; function is supported
981
        retf
1065 Lrz 982
 
983
secondary_loader_info:
1132 Lrz 984
        dw      0, 0x1000
985
        dw      0x30000 / 0x1000
986
        db      'kord/loader',0
987
aKernelNotFound db      'Fatal error: cannot load the secondary loader',0
1065 Lrz 988
 
989
align 2
990
cachelist:
1132 Lrz 991
.head           dw      cachelist
992
.tail           dw      cachelist
993
free_cache_item dw      0
994
last_cache_item dw      0x8400
1065 Lrz 995
 
1132 Lrz 996
use_path_table  db      0
997
bootdrive       db      ?
1065 Lrz 998
align 2
1132 Lrz 999
lb_size         dw      ?       ; Logical Block size in bytes
1000
                dw      0       ; to allow access dword [lb_size]
1001
lb_per_sec      dw      ?       ; Logical Blocks per physical sector
1002
                dw      0       ; to allow access dword [lb_per_sec]
1003
free_ptr        dw      ?       ; first free block in cache (cache block = sector = 0x800 bytes)
1004
size_rest       dw      ?       ; free space in cache (in blocks)
1005
cache_size      dw      ?
1006
cache_start     dw      ?
1007
pathtable_size  dw      ?
1008
pathtable_start dw      ?
1009
root_location   dd      ?
1010
cur_desc_end    dw      ?
1011
cur_nocache_len dd      ?
1012
cur_limit       dd      ?
1013
cur_unit_limit  dd      ?
1014
overflow        dw      ?
1015
cur_chunk       dw      ?
1016
first_byte      dw      ?
1017
cur_start       dd      ?
1065 Lrz 1018
 
1132 Lrz 1019
;times 83FEh-$  db      0
1020
        db      43h
1065 Lrz 1021
; just to make file 2048 bytes long :)
1132 Lrz 1022
        db      'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd'
1065 Lrz 1023
 
1132 Lrz 1024
        dw      0xAA55          ; this is not required for CD, but to be consistent...