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
 
27
; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond
28
; It is used when main bootloader is Windows loader.
29
 
30
; this code is loaded:
31
; NT/2k/XP: by ntldr to 0D00:0000
32
; 9x: by io.sys from config.sys to xxxx:0100
33
; Vista: by bootmgr to 0000:7C00
2434 Serge 34
        format binary
35
        use16
1065 Lrz 36
 
37
; in any case, we relocate this code to 0000:0600
2434 Serge 38
        org 0x600
1065 Lrz 39
; entry point for 9x and Vista booting
2434 Serge 40
        call    @f
41
        db      'NTFS'
1065 Lrz 42
@@:
2434 Serge 43
        pop     si
44
        sub     si, 3
45
        cmp     si, 100h
46
        jnz     boot_vista
47
        mov     si, load_question + 100h - 600h
48
        call    out_string
49
;       mov     si, answer + 100h - 0600h               ; already is
50
xxy:
51
        mov     ah, 0
52
        int     16h
53
        or      al, 20h
54
        mov     [si], al
55
        cmp     al, 'y'
56
        jz      xxz
57
        cmp     al, 'n'
58
        jnz     xxy
1065 Lrz 59
; continue load Windows
2434 Serge 60
;       call    out_string
61
;       ret
1065 Lrz 62
out_string:
2434 Serge 63
        push    bx
1065 Lrz 64
@@:
2434 Serge 65
        lodsb
66
        test    al, al
67
        jz      @f
68
        mov     ah, 0Eh
69
        mov     bx, 7
70
        int     10h
71
        jmp     @b
1065 Lrz 72
@@:
2434 Serge 73
        pop     bx
74
        ret
1065 Lrz 75
xxz:
76
; boot KordOS
2434 Serge 77
        call    out_string
1065 Lrz 78
; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers,
79
; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached
2434 Serge 80
        xor     di, di
81
        mov     ds, di
82
        mov     word [di+4], new01handler + 100h - 600h
83
        mov     [di+6], cs
84
        pushf
85
        pop     ax
86
        or      ah, 1
87
        push    ax
88
        popf
1065 Lrz 89
; we cannot issue INT 19h directly, because INT command clears TF
2434 Serge 90
;       int     19h     ; don't issue it directly, because INT command clears TF
1065 Lrz 91
; so instead we use direct call
2434 Serge 92
;       pushf           ; there will be no IRET
93
        call    far [di + 19h*4]
1065 Lrz 94
xxt:
2434 Serge 95
        xor     di, di
96
        mov     ds, di
97
        cmp     word [di + 8*4+2], 0F000h
98
        jz      @f
99
        les     bx, [di + 8*4]
100
        mov     eax, [es:bx+1]
101
        mov     [di + 8*4], eax
1065 Lrz 102
@@:
2434 Serge 103
        mov     si, 100h
1065 Lrz 104
boot_vista:
105
; relocate cs:si -> 0000:0600
2434 Serge 106
        push    cs
107
        pop     ds
108
        xor     ax, ax
109
        mov     es, ax
110
        mov     di, 0x600
111
        mov     cx, 2000h/2
112
        rep movsw
113
        jmp     0:real_entry
1065 Lrz 114
 
2434 Serge 115
load_question   db      'Load KordOS? [y/n]: ',0
116
answer  db      ?
117
        db      13,10,0
1065 Lrz 118
 
119
new01handler:
120
; [sp]=ip, [sp+2]=cs, [sp+4]=flags
2434 Serge 121
        push    bp
122
        mov     bp, sp
123
        push    ds
124
        lds     bp, [bp+2]
125
        cmp     word [ds:bp], 19cdh
126
        jz      xxt
127
        pop     ds
128
        pop     bp
129
        iret
1065 Lrz 130
 
131
; read from hard disk
132
; in: eax = absolute sector
133
;     cx = number of sectors
134
;     es:bx -> buffer
135
; out: CF=1 if error
136
read:
2434 Serge 137
        pushad
138
        add     eax, [bp + partition_start - dat]
139
        cmp     [bp + use_lba - dat], 0
140
        jz      .chs
1065 Lrz 141
; LBA read
2434 Serge 142
        push    ds
1065 Lrz 143
.lbado:
2434 Serge 144
        push    ax
145
        push    cx
146
        cmp     cx, 0x7F
147
        jbe     @f
148
        mov     cx, 0x7F
1065 Lrz 149
@@:
150
; create disk address packet on the stack
151
; dq starting LBA
2434 Serge 152
        push    0
153
        push    0
154
        push    eax
1065 Lrz 155
; dd buffer
2434 Serge 156
        push    es
157
        push    bx
1065 Lrz 158
; dw number of blocks to transfer (no more than 0x7F)
2434 Serge 159
        push    cx
1065 Lrz 160
; dw packet size in bytes
2434 Serge 161
        push    10h
1065 Lrz 162
; issue BIOS call
2434 Serge 163
        push    ss
164
        pop     ds
165
        mov     si, sp
166
        mov     dl, [bp + boot_drive - dat]
167
        mov     ah, 42h
168
        int     13h
169
        jc      .disk_error_lba
170
        add     sp, 10h         ; restore stack
1065 Lrz 171
; increase current sector & buffer; decrease number of sectors
2434 Serge 172
        movzx   esi, cx
173
        mov     ax, es
174
        shl     cx, 5
175
        add     ax, cx
176
        mov     es, ax
177
        pop     cx
178
        pop     ax
179
        add     eax, esi
180
        sub     cx, si
181
        jnz     .lbado
182
        pop     ds
183
        popad
184
        ret
1065 Lrz 185
.disk_error_lba:
2434 Serge 186
        add     sp, 14h
187
        pop     ds
188
        popad
189
        stc
190
        ret
1065 Lrz 191
 
192
.chs:
2434 Serge 193
        pusha
194
        pop     edi             ; loword(edi) = di, hiword(edi) = si
195
        push    bx
1065 Lrz 196
 
197
; eax / (SectorsPerTrack) -> eax, remainder bx
2434 Serge 198
        movzx   esi, [bp + sectors - dat]
199
        xor     edx, edx
200
        div     esi
201
        mov     bx, dx          ; bx = sector-1
1065 Lrz 202
 
203
; eax -> dx:ax
2434 Serge 204
        push    eax
205
        pop     ax
206
        pop     dx
1065 Lrz 207
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx
2434 Serge 208
        div     [bp + heads - dat]
1065 Lrz 209
 
210
; number of sectors: read no more than to end of track
2434 Serge 211
        sub     si, bx
212
        cmp     cx, si
213
        jbe     @f
214
        mov     cx, si
1065 Lrz 215
@@:
216
 
2434 Serge 217
        inc     bx
1065 Lrz 218
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector
219
; convert to int13 format
2434 Serge 220
        movzx   edi, cx
221
        mov     dh, dl
222
        mov     dl, [bp + boot_drive - dat]
223
        shl     ah, 6
224
        mov     ch, al
225
        mov     al, cl
226
        mov     cl, bl
227
        or      cl, ah
228
        pop     bx
229
        mov     si, 3
230
        mov     ah, 2
1065 Lrz 231
@@:
2434 Serge 232
        push    ax
233
        int     13h
234
        jnc     @f
235
        xor     ax, ax
236
        int     13h     ; reset drive
237
        pop     ax
238
        dec     si
239
        jnz     @b
240
        add     sp, 12
241
        popad
242
        stc
243
        ret
1065 Lrz 244
@@:
2434 Serge 245
        pop     ax
246
        mov     ax, es
247
        mov     cx, di
248
        shl     cx, 5
249
        add     ax, cx
250
        mov     es, ax
251
        push    edi
252
        popa
253
        add     eax, edi
254
        sub     cx, di
255
        jnz     .chs
256
        popad
257
        ret
1065 Lrz 258
 
2434 Serge 259
disk_error2     db      'Fatal: cannot read partitions info: '
260
disk_error_msg  db      'disk read error',0
261
disk_params_msg db      'Fatal: cannot get drive parameters',0
262
start_msg       db      2,' KordOS bootloader',13,10,0
263
part_msg        db      'looking at partition '
264
part_char       db      '0'     ; will be incremented before writing message
265
                db      ' ... ',0
266
errfs_msg       db      'unknown filesystem',13,10,0
267
fatxx_msg       db      'FATxx'
268
newline         db      13,10,0
269
ntfs_msg        db      'NTFS',13,10,0
270
error_msg       db      'Error'
271
colon           db      ': ',0
272
root_string     db      '\',0
273
nomem_msg       db      'No memory',0
274
filesys_string  db      '(filesystem)',0
275
directory_string db     'is a directory',0
276
notdir_string   db      'not a directory',0
1065 Lrz 277
 
278
; entry point for NT/2k/XP booting
279
; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256
2434 Serge 280
        repeat  600h + 256h - $
281
                db      1       ; any data can be here; 1 in ASCII is a nice face :)
282
        end repeat
1065 Lrz 283
; cs=es=0D00, ds=07C0, ss=0
284
; esi=edi=ebp=0, esp=7C00
2434 Serge 285
        xor     si, si
286
        jmp     boot_vista
1065 Lrz 287
 
288
real_entry:
289
; ax = 0
2434 Serge 290
        mov     ds, ax
291
        mov     es, ax
1065 Lrz 292
; our stack is 4 Kb: memory range 2000-3000
2434 Serge 293
        mov     ss, ax
294
        mov     sp, 3000h
295
        mov     bp, dat
296
        sti     ; just for case
1065 Lrz 297
; say hi to user
2434 Serge 298
        mov     si, start_msg
299
        call    out_string
1065 Lrz 300
; we are booting from hard disk identified by [boot_drive]
2434 Serge 301
        mov     dl, [bp + boot_drive - dat]
1065 Lrz 302
; is LBA supported?
2434 Serge 303
        mov     [bp + use_lba - dat], 0
304
        mov     ah, 41h
305
        mov     bx, 55AAh
306
        int     13h
307
        jc      .no_lba
308
        cmp     bx, 0AA55h
309
        jnz     .no_lba
310
        test    cl, 1
311
        jz      .no_lba
312
        inc     [bp + use_lba - dat]
313
        jmp     disk_params_ok
1065 Lrz 314
.no_lba:
315
; get drive geometry
2434 Serge 316
        mov     ah, 8
317
        mov     dl, [bp + boot_drive - dat]
318
        int     13h
319
        jnc     @f
320
        mov     si, disk_params_msg
321
        call    out_string
322
        jmp     $
1065 Lrz 323
@@:
2434 Serge 324
        movzx   ax, dh
325
        inc     ax
326
        mov     [bp + heads - dat], ax
327
        and     cx, 3Fh
328
        mov     [bp + sectors - dat], cx
1065 Lrz 329
disk_params_ok:
330
; determine size of cache for folders
2434 Serge 331
        int     12h     ; ax = size of available base memory in Kb
332
        sub     ax, 94000h / 1024
333
        jc      nomem
334
        shr     ax, 3
335
        mov     [bp + cachelimit - dat], ax     ; size of cache - 1
1065 Lrz 336
; scan all partitions
337
new_partition_ex:
2434 Serge 338
        xor     eax, eax        ; read first sector of current disk area
339
        mov     [bp + extended_part_cur - dat], eax     ; no extended partition yet
340
        mov     [bp + cur_partition_ofs - dat], 31BEh   ; start from first partition
341
        push    es
342
        mov     cx, 1
343
        mov     bx, 3000h
344
        call    read
345
        pop     es
346
        jnc     new_partition
347
        mov     si, disk_error2
348
        call    out_string
349
        jmp     $
1065 Lrz 350
new_partition:
2434 Serge 351
        mov     bx, [bp + cur_partition_ofs - dat]
352
        mov     al, [bx+4]      ; partition type
353
        test    al, al
354
        jz      next_partition
355
        cmp     al, 5
356
        jz      @f
357
        cmp     al, 0xF
358
        jnz     not_extended
1065 Lrz 359
@@:
360
; extended partition
2434 Serge 361
        mov     eax, [bx+8]     ; partition start
362
        add     eax, [bp + extended_part_start - dat]
363
        mov     [bp + extended_part_cur - dat], eax
1065 Lrz 364
next_partition:
2434 Serge 365
        add     [bp + cur_partition_ofs - dat], 10h
366
        cmp     [bp + cur_partition_ofs - dat], 31FEh
367
        jb      new_partition
368
        mov     eax, [bp + extended_part_cur - dat]
369
        test    eax, eax
370
        jz      partitions_done
371
        cmp     [bp + extended_part_start - dat], 0
372
        jnz     @f
373
        mov     [bp + extended_part_start - dat], eax
1065 Lrz 374
@@:
2434 Serge 375
        mov     [bp + extended_parent - dat], eax
376
        mov     [bp + partition_start - dat], eax
377
        jmp     new_partition_ex
1065 Lrz 378
partitions_done:
2434 Serge 379
        mov     si, total_kaput
380
        call    out_string
381
        jmp     $
1065 Lrz 382
not_extended:
2434 Serge 383
        mov     eax, [bx+8]
384
        add     eax, [bp + extended_parent - dat]
385
        mov     [bp + partition_start - dat], eax
1065 Lrz 386
; try to load from current partition
387
; inform user
2434 Serge 388
        mov     si, part_msg
389
        inc     [si + part_char - part_msg]
390
        call    out_string
1065 Lrz 391
; read bootsector
2434 Serge 392
        xor     eax, eax
393
        mov     [bp + cur_obj - dat], filesys_string
394
        push    es
395
        mov     cx, 1
396
        mov     bx, 3200h
397
        call    read
398
        pop     es
399
        mov     si, disk_error_msg
400
        jc      find_error_si
401
        movzx   si, byte [bx+13]
402
        mov     word [bp + sect_per_clust - dat], si
403
        test    si, si
404
        jz      unknown_fs
405
        lea     ax, [si-1]
406
        test    si, ax
407
        jnz     unknown_fs
1065 Lrz 408
; determine file system
409
; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h)
2434 Serge 410
        cmp     word [bx+11], 0x200
411
        jnz     unknown_fs
1065 Lrz 412
; is it NTFS?
2434 Serge 413
        cmp     dword [bx+3], 'NTFS'
414
        jnz     not_ntfs
415
        cmp     byte [bx+16], bl
416
        jz      ntfs
1065 Lrz 417
not_ntfs:
418
; is it FAT? FAT12/FAT16/FAT32?
419
; get count of sectors to dword in cx:si
2434 Serge 420
        mov     si, [bx+19]
421
        xor     cx, cx
422
        test    si, si
423
        jnz     @f
424
        mov     si, [bx+32]
425
        mov     cx, [bx+34]
1065 Lrz 426
@@:
2434 Serge 427
        xor     eax, eax
1065 Lrz 428
; subtract size of system area
2434 Serge 429
        sub     si, [bx+14]     ; BPB_ResvdSecCnt
430
        sbb     cx, ax
431
        mov     ax, [bx+17]     ; BPB_RootEntCnt
432
        add     ax, 0xF
433
        rcr     ax, 1
434
        shr     ax, 3
435
        sub     si, ax
436
        sbb     cx, 0
437
        push    cx
438
        push    si
439
        mov     ax, word [bx+22]
440
        test    ax, ax
441
        jnz     @f
442
        mov     eax, [bx+36]
1065 Lrz 443
@@:
2434 Serge 444
        movzx   ecx, byte [bx+16]
445
        imul    ecx, eax
446
        pop     eax
447
        sub     eax, ecx
1065 Lrz 448
; now eax = count of sectors in the data region
2434 Serge 449
        xor     edx, edx
450
        div     [bp + sect_per_clust - dat]
1065 Lrz 451
; now eax = count of clusters in the data region
2434 Serge 452
        mov     si, fatxx_msg
453
        cmp     eax, 0xFFF5
454
        jae     test_fat32
1065 Lrz 455
; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38
2434 Serge 456
        cmp     byte [bx+38], 0x29
457
        jnz     not_fat
458
        cmp     ax, 0xFF5
459
        jae     fat16
1065 Lrz 460
fat12:
2434 Serge 461
        mov     [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster
462
        mov     di, cx          ; BPB_NumFATs
463
        mov     ax, '12'
464
        push    ax              ; save for secondary loader
465
        mov     word [si+3], ax
466
        call    out_string
467
        movzx   ecx, word [bx+22]       ; BPB_FATSz16
1065 Lrz 468
; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes)
469
.fatloop:
470
; if first copy is not readable, try to switch to other copies
2434 Serge 471
        push    0x6000
472
        pop     es
473
        xor     bx, bx
474
        movzx   eax, word [0x320E]      ; BPB_RsvdSecCnt
475
        push    cx
476
        cmp     cx, 12
477
        jb      @f
478
        mov     cx, 12
1065 Lrz 479
@@:
2434 Serge 480
        call    read
481
        pop     cx
482
        jnc     fat1x_common
483
        add     eax, ecx        ; switch to next copy of FAT
484
        dec     di
485
        jnz     .fatloop
486
        mov     si, disk_error_msg
487
        jmp     find_error_si
1065 Lrz 488
fat16:
2434 Serge 489
        mov     [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster
490
        mov     ax, '16'
491
        push    ax              ; save for secondary loader
492
        mov     word [si+3], ax
493
        call    out_string
1065 Lrz 494
; FAT16: init FAT cache - no sectors loaded
2434 Serge 495
        mov     di, 0x3400
496
        xor     ax, ax
497
        mov     cx, 0x100/2
498
        rep stosw
1065 Lrz 499
fat1x_common:
2434 Serge 500
        mov     bx, 0x3200
501
        movzx   eax, word [bx+22]       ; BPB_FATSz16
502
        xor     esi, esi        ; no root cluster
503
        jmp     fat_common
1065 Lrz 504
test_fat32:
505
; FAT32 bootsector has it at the offset +66
2434 Serge 506
        cmp     byte [bx+66], 0x29
507
        jnz     not_fat
508
        mov     [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster
509
        mov     ax, '32'
510
        push    ax              ; save for secondary loader
511
        mov     word [si+3], ax
512
        call    out_string
1065 Lrz 513
; FAT32 - init cache for FAT table: no sectors loaded
2434 Serge 514
        lea     si, [bp + cache1head - dat]
515
        mov     [si], si                ; no sectors in cache:
516
        mov     [si+2], si              ; 'prev' & 'next' links point to self
517
        mov     [bp + cache1end - dat], 3400h   ; first free item = 3400h
518
        mov     [bp + cache1limit - dat], 3C00h
519
        mov     eax, [bx+36]    ; BPB_FATSz32
520
        mov     esi, [bx+44]    ; BPB_RootClus
521
        jmp     fat_common
1065 Lrz 522
not_fat:
523
unknown_fs:
2434 Serge 524
        mov     si, errfs_msg
525
        call    out_string
526
        jmp     next_partition
1065 Lrz 527
fat_common:
2434 Serge 528
        push    ss
529
        pop     es
530
        movzx   edx, byte [bx+16]       ; BPB_NumFATs
531
        mul     edx
532
        mov     [bp + root_start - dat], eax    ; this is for FAT1x
1065 Lrz 533
; eax = total size of all FAT tables, in sectors
2434 Serge 534
        movzx   ecx, word [bx+17]       ; BPB_RootEntCnt
535
        add     ecx, 0xF
536
        shr     ecx, 4
537
        add     eax, ecx
538
        mov     cx, word [bx+14]        ; BPB_RsvdSecCnt
539
        add     [bp + root_start - dat], ecx    ; this is for FAT1x
540
        add     eax, ecx
1065 Lrz 541
; cluster 2 begins from sector eax
2434 Serge 542
        movzx   ebx, byte [bx+13]       ; BPB_SecPerClus
543
        sub     eax, ebx
544
        sub     eax, ebx
545
        mov     [bp + data_start - dat], eax
1065 Lrz 546
; no clusters in folders cache
2434 Serge 547
        mov     di, foldcache_clus - 2
548
        xor     ax, ax
549
        mov     cx, 7*8/2 + 1
550
        rep stosw
551
        mov     [bp + root_clus - dat], esi
1065 Lrz 552
; load secondary loader
2434 Serge 553
        mov     [bp + load_file_ptr - dat], load_file_fat
1065 Lrz 554
load_secondary:
2434 Serge 555
        push    0x1000
556
        pop     es
557
        xor     bx, bx
558
        mov     si, kernel_name
559
        mov     cx, 0x30000 / 0x200
560
        call    [bp + load_file_ptr - dat]
1065 Lrz 561
; say error if needed
2434 Serge 562
        mov     si, error_too_big
563
        dec     bx
564
        js      @f
565
        jz      find_error_si
566
        mov     si, disk_error_msg
567
        jmp     find_error_si
1065 Lrz 568
@@:
569
; fill loader information and jump to secondary loader
2434 Serge 570
        mov     al, 'h'         ; boot device: hard drive
571
        mov     ah, [bp + boot_drive - dat]
572
        sub     ah, 80h         ; boot device: identifier
573
        pop     bx              ; restore file system ID ('12'/'16'/'32'/'nt')
574
        mov     si, callback
575
        jmp     1000h:0000h
1065 Lrz 576
 
577
nomem:
2434 Serge 578
        mov     si, nomem_msg
579
        call    out_string
580
        jmp     $
1065 Lrz 581
 
582
ntfs:
2434 Serge 583
        push    'nt'            ; save for secondary loader
584
        mov     si, ntfs_msg
585
        call    out_string
586
        xor     eax, eax
587
        mov     [bp + data_start - dat], eax
588
        mov     ecx, [bx+40h]   ; frs_size
589
        cmp     cl, al
590
        jg      .1
591
        neg     cl
592
        inc     ax
593
        shl     eax, cl
594
        jmp     .2
1065 Lrz 595
.1:
2434 Serge 596
        mov     eax, ecx
597
        shl     eax, 9
1065 Lrz 598
.2:
2434 Serge 599
        mov     [bp + frs_size - dat], ax
1065 Lrz 600
; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different
601
; (at least with standard tools)
602
; we allow extra size, but no more than 0x1000 bytes = 4 Kb
2434 Serge 603
        mov     si, invalid_volume_msg
604
        cmp     eax, 0x1000
605
        ja      find_error_si
1065 Lrz 606
; must be multiple of sector size
2434 Serge 607
        test    ax, 0x1FF
608
        jnz     find_error_si
609
        shr     ax, 9
610
        xchg    cx, ax
1065 Lrz 611
; initialize cache - no data loaded
2434 Serge 612
        lea     si, [bp + cache1head - dat]
613
        mov     [si], si
614
        mov     [si+2], si
615
        mov     word [si+4], 3400h      ; first free item = 3400h
616
        mov     word [si+6], 3400h + 8*8        ; 8 items in this cache
1065 Lrz 617
; read first MFT record - description of MFT itself
2434 Serge 618
        mov     [bp + cur_obj - dat], mft_string
619
        mov     eax, [bx+30h]   ; mft_cluster
620
        mul     [bp + sect_per_clust - dat]
621
        push    0x8000
622
        pop     es
623
        xor     bx, bx
624
        push    es
625
        call    read
626
        pop     ds
627
        call    restore_usa
1065 Lrz 628
; scan for unnamed $DATA attribute
2434 Serge 629
        mov     [bp + freeattr - dat], 4000h
630
        mov     ax, 80h
631
        call    load_attr
632
        push    ss
633
        pop     ds
634
        mov     si, nodata_string
635
        jc      find_error_si
1065 Lrz 636
; load secondary loader
2434 Serge 637
        mov     [bp + load_file_ptr - dat], load_file_ntfs
638
        jmp     load_secondary
1065 Lrz 639
 
640
find_error_si:
2434 Serge 641
        push    si
1065 Lrz 642
find_error_sp:
2434 Serge 643
        cmp     [bp + in_callback - dat], 0
644
        jnz     error_in_callback
645
        push    ss
646
        pop     ds
647
        push    ss
648
        pop     es
649
        mov     si, error_msg
650
        call    out_string
651
        mov     si, [bp + cur_obj - dat]
1065 Lrz 652
@@:
2434 Serge 653
        lodsb
654
        test    al, al
655
        jz      @f
656
        cmp     al, '/'
657
        jz      @f
658
        mov     ah, 0Eh
659
        mov     bx, 7
660
        int     10h
661
        jmp     @b
1065 Lrz 662
@@:
2434 Serge 663
        mov     si, colon
664
        call    out_string
665
        pop     si
666
        call    out_string
667
        mov     si, newline
668
        call    out_string
669
        mov     sp, 0x3000
670
        jmp     next_partition
1065 Lrz 671
error_in_callback:
672
; return status: file not found, except for read errors
2434 Serge 673
        mov     bx, 2
674
        cmp     si, disk_error_msg
675
        jnz     @f
676
        inc     bx
1065 Lrz 677
@@:
2434 Serge 678
        mov     ax, 0xFFFF
679
        mov     dx, ax
680
        mov     sp, 3000h - 6
681
        ret
1065 Lrz 682
 
683
callback:
684
; in: ax = function number; only functions 1 and 2 are defined for now
685
; save caller's stack
2434 Serge 686
        mov     dx, ss
687
        mov     cx, sp
1065 Lrz 688
; set our stack (required because we need ss=0)
2434 Serge 689
        xor     si, si
690
        mov     ss, si
691
        mov     sp, 3000h
692
        mov     bp, dat
693
        mov     [bp + in_callback - dat], 1
694
        push    dx
695
        push    cx
1065 Lrz 696
; set ds:si -> ASCIIZ name
2434 Serge 697
        lea     si, [di+6]
1065 Lrz 698
; set cx = limit in sectors; 4Kb = 8 sectors
2434 Serge 699
        movzx   ecx, word [di+4]
700
        shl     cx, 3
1065 Lrz 701
; set es:bx = pointer to buffer
2434 Serge 702
        les     bx, [di]
1065 Lrz 703
; call our function
2434 Serge 704
        stc     ; unsupported function
705
        dec     ax
706
        jz      callback_readfile
707
        dec     ax
708
        jnz     callback_ret
709
        call    continue_load_file
710
        jmp     callback_ret_succ
1065 Lrz 711
callback_readfile:
712
; function 1: read file
713
; in: ds:di -> information structure
2434 Serge 714
;       dw:dw   address
715
;       dw      limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100)
716
;       ASCIIZ  name
1065 Lrz 717
; 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
718
; out: dx:ax = file size (0xFFFFFFFF if file was not found)
2434 Serge 719
        call    [bp + load_file_ptr - dat]
1065 Lrz 720
callback_ret_succ:
2434 Serge 721
        clc
1065 Lrz 722
callback_ret:
723
; restore caller's stack
2434 Serge 724
        pop     cx
725
        pop     ss
726
        mov     sp, cx
1065 Lrz 727
; return to caller
2434 Serge 728
        retf
1065 Lrz 729
 
730
read_file_chunk.resident:
731
; auxiliary label for read_file_chunk procedure
2434 Serge 732
        mov     di, bx
733
        lodsw
1065 Lrz 734
read_file_chunk.resident.continue:
2434 Serge 735
        mov     dx, ax
736
        add     dx, 0x1FF
737
        shr     dx, 9
738
        cmp     dx, cx
739
        jbe     @f
740
        mov     ax, cx
741
        shl     ax, 9
1065 Lrz 742
@@:
2434 Serge 743
        xchg    ax, cx
744
        rep movsb
745
        xchg    ax, cx
746
        clc     ; no disk error if no disk requests
747
        mov     word [bp + num_sectors - dat], ax
748
        ret
1065 Lrz 749
 
750
read_file_chunk:
751
; in: ds:si -> file chunk
752
; in: es:bx -> buffer for output
753
; in: ecx = maximum number of sectors to read (high word must be 0)
754
; out: CF=1 <=> disk read error
2434 Serge 755
        lodsb
756
        mov     [bp + cur_chunk_resident - dat], al
757
        test    al, al
758
        jz      .resident
1065 Lrz 759
; normal case: load (non-resident) attribute from disk
760
.read_block:
2434 Serge 761
        lodsd
762
        xchg    eax, edx
763
        test    edx, edx
764
        jz      .ret
765
        lodsd
1065 Lrz 766
; eax = start cluster, edx = number of clusters, cx = limit in sectors
2434 Serge 767
        imul    eax, [bp + sect_per_clust - dat]
768
        add     eax, [bp + data_start - dat]
769
        mov     [bp + cur_cluster - dat], eax
770
        imul    edx, [bp + sect_per_clust - dat]
771
        mov     [bp + num_sectors - dat], edx
772
        and     [bp + cur_delta - dat], 0
1065 Lrz 773
.nonresident.continue:
2434 Serge 774
        cmp     edx, ecx
775
        jb      @f
776
        mov     edx, ecx
1065 Lrz 777
@@:
2434 Serge 778
        test    dx, dx
779
        jz      .read_block
780
        add     [bp + cur_delta - dat], edx
781
        sub     [bp + num_sectors - dat], edx
782
        sub     ecx, edx
783
        push    cx
784
        mov     cx, dx
785
        call    read
786
        pop     cx
787
        jc      .ret
788
        test    cx, cx
789
        jnz     .read_block
1065 Lrz 790
.ret:
2434 Serge 791
        ret
1065 Lrz 792
 
793
cache_lookup:
794
; in: eax = value to look, si = pointer to cache structure
795
; out: di->cache entry; CF=1 <=> the value was not found
2434 Serge 796
        push    ds bx
797
        push    ss
798
        pop     ds
799
        mov     di, [si+2]
1065 Lrz 800
.look:
2434 Serge 801
        cmp     di, si
802
        jz      .not_in_cache
803
        cmp     eax, [di+4]
804
        jz      .in_cache
805
        mov     di, [di+2]
806
        jmp     .look
1065 Lrz 807
.not_in_cache:
808
; cache miss
809
; cache is full?
2434 Serge 810
        mov     di, [si+4]
811
        cmp     di, [si+6]
812
        jnz     .cache_not_full
1065 Lrz 813
; yes, delete the oldest entry
2434 Serge 814
        mov     di, [si]
815
        mov     bx, [di]
816
        mov     [si], bx
817
        push    word [di+2]
818
        pop     word [bx+2]
819
        jmp     .cache_append
1065 Lrz 820
.cache_not_full:
821
; no, allocate new item
2434 Serge 822
        add     word [si+4], 8
1065 Lrz 823
.cache_append:
2434 Serge 824
        mov     [di+4], eax
825
        stc
826
        jmp     @f
1065 Lrz 827
.in_cache:
828
; delete this sector from the list
2434 Serge 829
        push    si
830
        mov     si, [di]
831
        mov     bx, [di+2]
832
        mov     [si+2], bx
833
        mov     [bx], si
834
        pop     si
1065 Lrz 835
@@:
836
; add new sector to the end of list
2434 Serge 837
        mov     bx, di
838
        xchg    bx, [si+2]
839
        push    word [bx]
840
        pop     word [di]
841
        mov     [bx], di
842
        mov     [di+2], bx
843
        pop     bx ds
844
        ret
1065 Lrz 845
 
846
include 'fat.inc'
847
include 'ntfs.inc'
848
 
2434 Serge 849
total_kaput     db      13,10,'Fatal error: cannot load the secondary loader',0
850
error_too_big   db      'file is too big',0
851
nodata_string   db      '$DATA '
852
error_not_found db      'not found',0
853
noindex_string  db      '$INDEX_ROOT not found',0
854
badname_msg     db      'bad name for FAT',0
855
invalid_volume_msg db   'invalid volume',0
856
mft_string      db      '$MFT',0
857
fragmented_string db    'too fragmented file',0
1065 Lrz 858
invalid_read_request_string db 'cannot read attribute',0
859
 
2434 Serge 860
kernel_name     db      'kord/loader',0
1065 Lrz 861
 
862
align 4
863
dat:
864
 
2434 Serge 865
extended_part_start     dd      0       ; start sector for main extended partition
866
extended_part_cur       dd      ?       ; start sector for current extended child
867
extended_parent         dd      0       ; start sector for current extended parent
868
partition_start         dd      0       ; start sector for current logical disk
869
cur_partition_ofs       dw      ?       ; offset in MBR data for current partition
870
sect_per_clust          dd      0
1065 Lrz 871
; change this variable if you want to boot from other physical drive
2434 Serge 872
boot_drive      db      80h
873
in_callback     db      0
1065 Lrz 874
 
875
; uninitialized data
2434 Serge 876
use_lba         db      ?
877
cur_chunk_resident db   ?
1065 Lrz 878
align 2
2434 Serge 879
heads           dw      ?
880
sectors         dw      ?
881
cache1head      rw      2
882
cache1end       dw      ?
883
cache1limit     dw      ?
884
data_start      dd      ?
885
cachelimit      dw      ?
886
load_file_ptr   dw      ?
887
cur_obj         dw      ?
888
missing_slash   dw      ?
889
root_clus       dd      ?
890
root_start      dd      ?
891
get_next_cluster_ptr    dw      ?
892
frs_size        dw      ?
893
freeattr        dw      ?
894
index_root      dw      ?
895
index_alloc     dw      ?
896
cur_index_seg   dw      ?
897
cur_index_cache dw      ?
898
filesize        dd      ?
899
filesize_sectors dd     ?
900
cur_cluster     dd      ?
901
cur_delta       dd      ?
902
num_sectors     dd      ?
903
sectors_read    dd      ?
904
cur_chunk_ptr   dw      ?
1065 Lrz 905
 
2434 Serge 906
rootcache_size  dw      ?       ; must be immediately before foldcache_clus
1065 Lrz 907
if $-dat >= 0x80
2434 Serge 908
warning:
909
         unoptimal data displacement!
1065 Lrz 910
end if
2434 Serge 911
foldcache_clus  rd      7
912
foldcache_mark  rw      7
913
foldcache_size  rw      7
914
fat_filename    rb      11
1065 Lrz 915
 
916
if $ > 2000h
2434 Serge 917
error:
918
       file is too big
1065 Lrz 919
end if
920
 
921
; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long
922
repeat 0x2600 - $
2434 Serge 923
        db      2       ; any data can be here; 2 is another nice face in ASCII :)
1065 Lrz 924
end repeat