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
 
27
use_lba = 0
1132 Lrz 28
        org     0x7C00
29
        jmp     start
30
        nop
1065 Lrz 31
; FAT parameters, BPB
32
; note: they can be changed at install, replaced with real values
33
; these settings are for most typical 1.44M floppies
1132 Lrz 34
                db      'KOLIBRI '      ; BS_OEMName, ignored
35
                dw      200h            ; BPB_BytsPerSec
36
BPB_SecsPerClus db      1
37
BPB_RsvdSecCnt  dw      1
38
BPB_NumFATs     db      2
39
BPB_RootEntCnt  dw      0xE0
40
                dw      2880            ; BPB_TotSec16
41
                db      0xF0            ; BPB_Media
42
BPB_FATSz16     dw      9
43
BPB_SecPerTrk   dw      18
44
BPB_NumHeads    dw      2
45
BPB_HiddSec     dd      0
46
                dd      0               ; BPB_TotSec32
47
BS_DrvNum       db      0
48
                db      0               ; BS_Reserved1
49
                db      ')'             ; BS_BootSig
50
                dd      12344321h       ; BS_VolID
1065 Lrz 51
filename:
1132 Lrz 52
                db      'KORD.OS    '   ; BS_VolLab
53
                db      'FAT12   '      ; BS_FilSysType
1065 Lrz 54
; Used memory map:
1132 Lrz 55
;       8000:0000 - current directory
56
;       9000:0000 - root directory data [cached]
1065 Lrz 57
start:
1132 Lrz 58
        xor     ax, ax
59
        mov     ss, ax
60
        mov     sp, 0x7C00
61
        mov     ds, ax
62
        mov     bp, sp
63
        cld
64
        sti
65
        mov     [bp+BS_DrvNum-0x7C00], dl
1065 Lrz 66
if use_lba
1132 Lrz 67
        mov     ah, 41h
68
        mov     bx, 55AAh
69
        int     13h
70
        mov     si, aNoLBA
71
        jc      err_
72
        cmp     bx, 0AA55h
73
        jnz     err_
74
        test    cx, 1
75
        jz      err_
1065 Lrz 76
else
1132 Lrz 77
        mov     ah, 8
78
        int     13h
79
        jc      @f              ; on error, assume that BPB geometry is valid
80
        mov     al, dh
81
        mov     ah, 0
82
        inc     ax
83
        mov     [bp+BPB_NumHeads-0x7C00], ax
84
        and     cx, 3Fh
85
        mov     [bp+BPB_SecPerTrk-0x7C00], cx
1065 Lrz 86
@@:
87
end if
88
; get FAT parameters
1132 Lrz 89
        xor     bx, bx
90
        mov     al, [bp+BPB_NumFATs-0x7C00]
91
        mov     ah, 0
92
        mul     [bp+BPB_FATSz16-0x7C00]
93
        add     ax, [bp+BPB_RsvdSecCnt-0x7C00]
94
        adc     dx, bx
95
        push    dx
96
        push    ax      ; root directory start = dword [bp-4]
97
        mov     cx, [bp+BPB_RootEntCnt-0x7C00]
98
        add     cx, 0xF
99
        rcr     cx, 1
100
        shr     cx, 3   ; cx = size of root directory in sectors
101
        add     ax, cx
102
        adc     dx, bx
103
        push    dx
104
        push    ax      ; data start = dword [bp-8]
1065 Lrz 105
; load start of root directory (no more than 0x2000 bytes = 0x10 sectors)
1132 Lrz 106
        cmp     cx, 0x10
107
        jb      @f
108
        mov     cx, 0x10
1065 Lrz 109
@@:
1132 Lrz 110
        mov     ax, [bp-4]
111
        mov     dx, [bp-2]
112
        push    0x9000
113
        pop     es
114
        call    read_sectors
115
        add     word [bp-4], cx         ; dword [bp-4] = start of non-cached root data
116
        adc     word [bp-2], bx
1065 Lrz 117
; load kordldr.f12
1132 Lrz 118
        mov     si, main_loader
119
        call    lookup_in_root_dir
120
        jc      noloader
121
        test    byte [es:di+11], 10h    ; directory?
122
        jz      kordldr_ok
1065 Lrz 123
noloader:
1132 Lrz 124
        mov     si, aLoaderNotFound
125
err_:
126
        call    out_string
127
        mov     si, aPressAnyKey
128
        call    out_string
129
        xor     ax, ax
130
        int     16h
131
        int     18h
132
        jmp     $
1065 Lrz 133
kordldr_ok:
1132 Lrz 134
        mov     ax, [es:di+26]          ; get file cluster
135
        mov     bx, 0x7E00
136
        xor     cx, cx
137
        mov     es, cx
138
        sub     ax, 2
139
        jc      noloader
140
        push    bx      ; save return address: bx = 7E00
141
        mov     cl, [bp+BPB_SecsPerClus-0x7C00]
142
        mul     cx
1065 Lrz 143
; fall through - 'ret' in read_sectors will return to 7E00
144
 
145
read_sectors2:
146
; same as read_sectors, but dx:ax is relative to start of data
1132 Lrz 147
        add     ax, [bp-8]
148
        adc     dx, [bp-6]
1065 Lrz 149
read_sectors:
150
; ss:bp = 0:7C00
151
; es:bx = pointer to data
152
; dx:ax = first sector
153
; cx = number of sectors
1132 Lrz 154
        pusha
155
        add     ax, word [bp+BPB_HiddSec-0x7C00]
156
        adc     dx, word [bp+BPB_HiddSec+2-0x7C00]
1065 Lrz 157
if use_lba
1132 Lrz 158
        push    ds
1065 Lrz 159
do_read_sectors:
1132 Lrz 160
        push    ax
161
        push    cx
162
        push    dx
163
        cmp     cx, 0x7F
164
        jbe     @f
165
        mov     cx, 0x7F
1065 Lrz 166
@@:
167
; create disk address packet on the stack
168
; dq starting LBA
1132 Lrz 169
        push    0
170
        push    0
171
        push    dx
172
        push    ax
1065 Lrz 173
; dd buffer
1132 Lrz 174
        push    es
175
        push    bx
1065 Lrz 176
; dw number of blocks to transfer (no more than 0x7F)
1132 Lrz 177
        push    cx
1065 Lrz 178
; dw packet size in bytes
1132 Lrz 179
        push    10h
1065 Lrz 180
; issue BIOS call
1132 Lrz 181
        push    ss
182
        pop     ds
183
        mov     si, sp
184
        mov     dl, [bp+BS_DrvNum-0x7C00]
185
        mov     ah, 42h
186
        int     13h
187
        mov     si, aReadError
188
        jc      err_
1065 Lrz 189
; restore stack
1132 Lrz 190
        add     sp, 10h
1065 Lrz 191
; increase current sector & buffer; decrease number of sectors
1132 Lrz 192
        mov     si, cx
193
        mov     ax, es
194
        shl     cx, 5
195
        add     ax, cx
196
        mov     es, ax
197
        pop     dx
198
        pop     cx
199
        pop     ax
200
        add     ax, si
201
        adc     dx, 0
202
        sub     cx, si
203
        jnz     do_read_sectors
204
        pop     ds
205
        popa
206
        ret
1065 Lrz 207
else
208
do_read_sectors:
1132 Lrz 209
        pusha
210
        pop     di
211
        push    bx
1065 Lrz 212
 
213
; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx
1132 Lrz 214
        mov     si, ax
215
        xchg    ax, dx
216
        xor     dx, dx
217
        div     [bp+BPB_SecPerTrk-0x7C00]
218
        push    ax
219
        mov     ax, si
220
        div     [bp+BPB_SecPerTrk-0x7C00]
221
        mov     bx, dx          ; bx=sector-1
222
        pop     dx
1065 Lrz 223
 
224
; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx
1132 Lrz 225
        div     [bp+BPB_NumHeads-0x7C00]
1065 Lrz 226
 
227
; number of sectors: read no more than to end of track
1132 Lrz 228
        push    bx
229
        sub     bx, [bp+BPB_SecPerTrk-0x7C00]
230
        neg     bx
231
        cmp     cx, bx
232
        jbe     @f
233
        mov     cx, bx
1065 Lrz 234
@@:
1132 Lrz 235
        pop     bx
1065 Lrz 236
 
1132 Lrz 237
        inc     bx
1065 Lrz 238
; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format
1132 Lrz 239
        mov     di, cx
240
        mov     dh, dl
241
        mov     dl, [bp+BS_DrvNum-0x7C00]
242
        shl     ah, 6
243
        mov     ch, al
244
        mov     al, cl
245
        mov     cl, bl
246
        or      cl, ah
247
        pop     bx
248
        mov     si, 3
249
        mov     ah, 2
1065 Lrz 250
@@:
1132 Lrz 251
        push    ax
252
        int     13h
253
        jnc     @f
254
        xor     ax, ax
255
        int     13h     ; reset drive
256
        pop     ax
257
        dec     si
258
        jnz     @b
259
        mov     si, aReadError
260
        jmp     err_
1065 Lrz 261
@@:
1132 Lrz 262
        pop     ax
263
        mov     ax, es
264
        mov     cx, di
265
        shl     cx, 5
266
        add     ax, cx
267
        mov     es, ax
268
        push    di
269
        popa
270
        add     ax, di
271
        adc     dx, 0
272
        sub     cx, di
273
        jnz     do_read_sectors
274
        popa
275
        ret
1065 Lrz 276
end if
277
 
278
scan_for_filename:
279
; in: ds:si -> 11-bytes FAT name
280
; in: es:0 -> part of directory data
281
; in: cx = number of entries
282
; out: if found: CF=0, ZF=1, es:di -> directory entry
283
; out: if not found, but continue required: CF=1 and ZF=0
284
; out: if not found and zero item reached: CF=1 and ZF=1
1132 Lrz 285
        xor     di, di
286
        push    cx
1065 Lrz 287
sloop:
1132 Lrz 288
        cmp     byte [es:di], 0
289
        jz      snotfound
290
        test    byte [es:di+11], 8      ; volume label?
291
        jnz     scont                   ; ignore volume labels
292
        pusha
293
        mov     cx, 11
294
        repz    cmpsb
295
        popa
296
        jz      sdone
1065 Lrz 297
scont:
1132 Lrz 298
        add     di, 0x20
299
        loop    sloop
300
        inc     cx      ; clear ZF flag
1065 Lrz 301
snotfound:
1132 Lrz 302
        stc
1065 Lrz 303
sdone:
1132 Lrz 304
        pop     cx
1065 Lrz 305
lrdret:
1132 Lrz 306
        ret
1065 Lrz 307
 
308
lookup_in_root_dir:
309
; ss:bp = 0:7C00
310
; in: ds:si -> 11-bytes FAT name
311
; out: if found: CF=0, es:di -> directory entry
312
; out: if not found: CF=1
1132 Lrz 313
        mov     cx, [bp+BPB_RootEntCnt-0x7C00]
314
        push    cx
1065 Lrz 315
; first, look in root directory cache
1132 Lrz 316
        push    0x9000
317
        pop     es
318
        test    ch, ch
319
        jz      @f
320
        mov     cx, 0x100
1065 Lrz 321
@@:
1132 Lrz 322
        mov     ax, [bp-4]
323
        mov     dx, [bp-2]      ; dx:ax = starting sector of not cached data of root directory
1065 Lrz 324
lrdloop:
1132 Lrz 325
        call    scan_for_filename
326
        pop     bx
327
        jz      lrdret
328
        sub     bx, cx
329
        mov     cx, bx
330
        stc
331
        jz      lrdret
1065 Lrz 332
; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries
1132 Lrz 333
        push    cx
334
        cmp     ch, 0x8
335
        jb      @f
336
        mov     cx, 0x800
1065 Lrz 337
@@:
1132 Lrz 338
        push    0x8000
339
        pop     es
340
        push    cx
341
        push    es
342
        xor     bx, bx
343
        add     cx, 0xF
344
        shr     cx, 4
345
        call    read_sectors
346
        pop     es
347
        add     ax, cx
348
        adc     dx, bx
349
        pop     cx
350
        jmp     lrdloop
1065 Lrz 351
 
352
out_string:
353
; in: ds:si -> ASCIIZ string
1132 Lrz 354
        lodsb
355
        test    al, al
356
        jz      lrdret
357
        mov     ah, 0Eh
358
        mov     bx, 7
359
        int     10h
360
        jmp     out_string
1065 Lrz 361
 
1132 Lrz 362
aReadError      db      'Read error',0
1065 Lrz 363
if use_lba
1132 Lrz 364
aNoLBA          db      'The drive does not support LBA!',0
1065 Lrz 365
end if
1132 Lrz 366
aLoaderNotFound db      'Loader not found',0
367
aPressAnyKey    db      13,10,'Press any key...',13,10,0
368
main_loader     db      'KORDLDR F1X'
1065 Lrz 369
 
370
if use_lba
1132 Lrz 371
        db      0       ; make bootsector 512 bytes in length
1065 Lrz 372
end if
373
 
374
; bootsector signature
1132 Lrz 375
        dw      0xAA55
1065 Lrz 376
 
377
; display offsets of all procedures used by kordldr.f12.asm
378
macro show [procedure]
379
{
1132 Lrz 380
        bits = 16
381
        display `procedure,' = '
382
        repeat bits/4
383
                d = '0' + procedure shr (bits - %*4) and 0Fh
384
                if d > '9'
385
                        d = d + 'A'-'9'-1
386
                end if
387
                display d
388
        end repeat
389
        display 13,10
1065 Lrz 390
}
391
 
1132 Lrz 392
show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader