Subversion Repositories Kolibri OS

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ha 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;;  FAT32.INC                                                      ;;
4
;;                                                                 ;;
5
;;  FAT16/32 functions for MenuetOS                                ;;
6
;;                                                                 ;;
7
;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
8
;;                                                                 ;;
9
;;  See file COPYING for details                                   ;;
10
;;                                                                 ;;
11
;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
12
;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
13
;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
14
;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
15
;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
16
;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
17
;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
18
;;  08.11.2004 rename - ATV                                        ;;
19
;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
20
;;  20.10.2004 Makedir/Removedir - ATV                             ;;
21
;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
22
;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
23
;;  24.5.2004  Write back buffer for File_write -VT                ;;
24
;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
25
;;  30.3.2004  Error parameters at function return - VT            ;;
26
;;  01.5.2002  Bugfix in device write - VT                         ;;
27
;;  20.5.2002  Hd status check - VT                                ;;
28
;;  29.6.2002  Improved fat32 verification - VT                    ;;
29
;;                                                                 ;;
30
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31
 
32
cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
33
 
52 mikedld 34
ERROR_SUCCESS        = 0
35
ERROR_DISK_BASE      = 1
36
ERROR_UNSUPPORTED_FS = 2
37
ERROR_UNKNOWN_FS     = 3
38
ERROR_PARTITION      = 4
39
ERROR_FILE_NOT_FOUND = 5
40
ERROR_END_OF_FILE    = 6
41
ERROR_MEMORY_POINTER = 7
42
ERROR_DISK_FULL      = 8
43
ERROR_FAT_TABLE      = 9
44
ERROR_ACCESS_DENIED  = 10
1 ha 45
 
46
PUSHAD_EAX equ [esp+28]
47
PUSHAD_ECX equ [esp+24]
48
PUSHAD_EDX equ [esp+20]
49
PUSHAD_EBX equ [esp+16]
50
PUSHAD_EBP equ [esp+8]
51
PUSHAD_ESI equ [esp+4]
52
PUSHAD_EDI equ [esp+0]
53
 
54
align 4
55
;******************************************************
56
; Please do not change this place - variables  in text
57
; Mario79
58
; START place
59
;******************************************************
60
PARTITION_START      dd 0x3f
61
PARTITION_END        dd 0
62
SECTORS_PER_FAT      dd 0x1f3a
63
NUMBER_OF_FATS       dd 0x2
64
SECTORS_PER_CLUSTER  dd 0x8
65
BYTES_PER_SECTOR     dd 0x200   ; Note: if BPS <> 512 need lots of changes
66
ROOT_CLUSTER         dd 2       ; first rootdir cluster
67
FAT_START            dd 0       ; start of fat table
68
ROOT_START           dd 0       ; start of rootdir (only fat16)
69
ROOT_SECTORS         dd 0       ; count of rootdir sectors (only fat16)
70
DATA_START           dd 0       ; start of data area (=first cluster 2)
71
LAST_CLUSTER         dd 0       ; last availabe cluster
72
ADR_FSINFO           dd 0       ; used only by fat32
73
 
74
fatRESERVED          dd 0x0FFFFFF6
75
fatBAD               dd 0x0FFFFFF7
76
fatEND               dd 0x0FFFFFF8
77
fatMASK              dd 0x0FFFFFFF
78
 
79
fat_type             db 0       ; 0=none, 16=fat16, 32=fat32
80
;***************************************************************************
81
; End place
82
; Mario79
83
;***************************************************************************
84
cluster              dd 0       ; used by file_write,makedir,append
85
partition_count      dd 0       ; partitions found by set_FAT32_variables
86
longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
87
longname_sec2        dd 0       ; directory sectors for delete long filename
88
 
89
hd_error             dd 0       ; set by wait_for_sector_buffer
90
hd_setup             dd 0
91
hd_wait_timeout      dd 0
92
 
93
cluster_tmp          dd 0       ; used by analyze_directory
94
                                ; and analyze_directory_to_write
95
 
96
file_size            dd 0       ; used by file_read
97
 
98
sector_tmp           dd 0       ; used by rename,append,file_write
99
entry_pos            dd 0       ; used by rename,append,file_write
100
 
101
old_filesize         dd 0       ; used by append
102
new_filepos          dd 0       ; used by append
103
bytes2write          dd 0       ; used by append
104
 
105
cache_search_start   dd 0       ; used by find_empty_slot
106
 
107
fat_in_cache         dd -1
108
fat_cache:           times 512 db 0
109
 
110
uglobal
111
 Sector512:                      ; label for dev_hdcd.inc
112
  buffer:              times 512 db 0
113
  deltree_buffer:      times 512 db 0
114
endg
115
 
116
iglobal
117
  NewDirEntry1         db ".          ",0x10
118
                     times 20 db 0
119
  NewDirEntry2         db "..         ",0x10
120
                     times 20 db 0
121
endg
122
 
123
uglobal
124
  dir_entry:           times 32 db 0
125
 
126
  startpath:           times 255 db 0
127
 
128
  fat16_root           db 0       ; flag for fat16 rootdir
129
  f_del                db 0       ; 1=overwrite fat entry
130
  fat_change           db 0       ; 1=fat has changed
131
 
132
endg
133
 
134
iglobal
135
  partition_types:              ; list of fat16/32 partitions
136
    db    0x04                  ; DOS: fat16 <32M
137
    db    0x06                  ; DOS: fat16 >32M
138
    db    0x0b                  ; WIN95: fat32
139
    db    0x0c                  ; WIN95: fat32, LBA-mapped
140
    db    0x0e                  ; WIN95: fat16, LBA-mapped
141
    db    0x14                  ; Hidden DOS: fat16 <32M
142
    db    0x16                  ; Hidden DOS: fat16 >32M
143
    db    0x1b                  ; Hidden WIN95: fat32
144
    db    0x1c                  ; Hidden WIN95: fat32, LBA-mapped
145
    db    0x1e                  ; Hidden WIN95: fat16, LBA-mapped
146
    db    0xc4                  ; DRDOS/secured: fat16 <32M
147
    db    0xc6                  ; DRDOS/secured: fat16 >32M
148
    db    0xcb                  ; DRDOS/secured: fat32
149
    db    0xcc                  ; DRDOS/secured: fat32, LBA-mapped
150
    db    0xce                  ; DRDOS/secured: fat16, LBA-mapped
151
    db    0xd4                  ; Old Multiuser DOS secured: fat16 <32M
152
    db    0xd6                  ; Old Multiuser DOS secured: fat16 >32M
153
  partition_types_end:
154
 
155
 
156
  extended_types:               ; list of extended partitions
157
    db    0x05                  ; DOS: extended partition
158
    db    0x0f                  ; WIN95: extended partition, LBA-mapped
159
    db    0xc5                  ; DRDOS/secured: extended partition
160
    db    0xd5                  ; Old Multiuser DOS secured: extended partition
161
  extended_types_end:
162
 
163
endg
164
 
165
 
166
reserve_hd1:
167
 
168
    cli
169
    cmp   [hd1_status],0
170
    je    reserve_ok1
171
 
172
    sti
173
    call  change_task
174
    jmp   reserve_hd1
175
 
176
  reserve_ok1:
177
 
178
    push  eax
179
    mov   eax,[0x3000]
180
    shl   eax,5
181
    mov   eax,[eax+0x3000+4]
182
    mov   [hd1_status],eax
183
    pop   eax
184
    sti
185
    ret
186
 
187
 
188
clear_hd_cache:
189
 
190
    push  eax ecx edi
191
    mov   edi,0x600000
192
    mov   ecx,16384
193
    xor   eax,eax
194
    cld
195
    rep   stosd                 ; clear hd cache with 0
196
    mov   [cache_search_start],eax
197
    mov   [fat_in_cache],-1
198
    mov   [fat_change],0
199
    pop   edi ecx eax
200
    ret
201
 
202
problem_partition db 0  ; used for partitions search
203
 
204
; Partition chain used:
205
; MBR        ;   PARTITION2 ;   PARTITION3 ;   PARTITION4
206
;==========================================================
207
; fat16/32   +-- fat16/32   +-- fat16/32   +-- fat16/32   +--
208
; extended --+   extended --+   extended --+   extended --+
209
; 0              0              0              0
210
; 0              0              0              0
211
; Notes:
212
; - extended partition need to be in second entry on table
213
; - it will skip over removed partitions
214
 
215
set_FAT32_variables:
216
    mov   [0xfe10],dword 0      ; entries in hd cache
217
    mov   [problem_partition],0
218
    call  reserve_hd1
219
    call  clear_hd_cache
220
 
221
    cmp   dword [hdpos],0
222
    je    problem_hd
223
 
224
    pushad
225
    xor   ecx,ecx               ; partition count
226
    mov   edx,-1                ; flag for partition
227
    xor   eax,eax               ; read MBR
228
    xor   ebp,ebp               ; extended partition start
229
 
230
new_partition:
231
    test  ebp,ebp               ; is there extended partition?
232
    jnz   extended_already_set  ; yes
233
    xchg  ebp,eax               ; no. set it now
234
 
235
extended_already_set:
236
    add   eax,ebp               ; mbr=mbr+0, ext_part=ext_start+relat_start
237
    mov   ebx,buffer
238
    call  hd_read
239
 
240
    cmp   word [ebx+0x1fe],0xaa55 ; is it valid boot sector?
241
    jnz   end_partition_chain
242
    cmp   dword [ebx+0x1be+0xc],0 ; skip over empty partition
243
    jz    next_partition
244
 
245
    push  eax ecx
246
    mov   edi,partition_types
247
    mov   ecx,partition_types_end-partition_types
248
    mov   al,[ebx+0x1be+4]      ; get partition type
249
    cld
250
    repne scasb                 ; is partition type ok?
251
    pop   ecx eax
252
    jnz   next_partition        ; no. skip over
253
 
254
    inc   ecx
255
    cmp   ecx,[fat32part]       ; is it wanted partition?
256
    jnz   next_partition        ; no
257
 
258
    mov   edx,eax               ; start sector
259
    add   edx,[ebx+0x1be+8]     ; add relative start
260
 
261
next_partition:
262
    push  ecx
263
    mov   edi,extended_types
264
    mov   ecx,extended_types_end-extended_types
265
    mov   al,[ebx+0x1be+4+16]   ; get second partition type
266
    cld
267
    repne scasb                 ; is it extended partition?
268
    pop   ecx
269
    jnz   end_partition_chain   ; no. end chain
270
 
271
    mov   eax,[ebx+0x1be+8+16]  ; get start of extended partition
272
    test  eax,eax               ; is there extended partition?
273
    jnz   new_partition         ; yes. read it
274
 
275
end_partition_chain:
276
    mov   [partition_count],ecx
277
 
278
    cmp   edx,-1                ; found wanted partition?
279
    jnz   hd_and_partition_ok   ; yes. install it
280
    jmp   problem_partition_or_fat
281
 
282
problem_fat_dec_count:          ; bootsector is missing or another problem
283
    dec   [partition_count]     ; remove it from partition_count
284
 
285
problem_partition_or_fat:
286
    popad
287
 
288
problem_hd:
289
    mov   [fat_type],0
290
    mov   [hd1_status],0        ; free
291
    mov   [problem_partition],1
292
    ret
293
 
294
hd_and_partition_ok:
295
    mov   eax,edx
296
    mov   [PARTITION_START],eax
297
 
298
    mov   [hd_setup],1
299
    mov   ebx,buffer
300
    call  hd_read               ; read boot sector of partition
301
    mov   [hd_setup],0
302
 
303
    cmp   word [ebx+0x1fe],0xaa55 ; is it valid boot sector?
304
    jnz   problem_fat_dec_count
305
 
306
    movzx eax,word [ebx+0xe]    ; sectors reserved
307
    add   eax,[PARTITION_START]
308
    mov   [FAT_START],eax       ; fat_start = partition_start + reserved
309
 
310
    movzx eax,byte [ebx+0xd]    ; sectors per cluster
311
    mov   [SECTORS_PER_CLUSTER],eax
312
 
313
    movzx ecx,word [ebx+0xb]    ; bytes per sector
314
    mov   [BYTES_PER_SECTOR],ecx
315
 
316
    movzx eax,word [ebx+0x11]   ; count of rootdir entries (=0 fat32)
317
    mov   edx,32
318
    mul   edx
319
    dec   ecx
320
    add   eax,ecx               ; round up if not equal count
321
    inc   ecx                   ; bytes per sector
322
    div   ecx
323
    mov   [ROOT_SECTORS],eax    ; count of rootdir sectors
324
 
325
    movzx eax,word [ebx+0x16]   ; sectors per fat <65536
326
    test  eax,eax
327
    jnz   fat16_fatsize
328
    mov   eax,[ebx+0x24]        ; sectors per fat
329
  fat16_fatsize:
330
    mov   [SECTORS_PER_FAT],eax
331
 
332
    movzx eax,byte [ebx+0x10]   ; number of fats
333
    test  eax,eax               ; if 0 it's not fat partition
334
    jz    problem_fat_dec_count
335
    mov   [NUMBER_OF_FATS],eax
336
    imul  eax,[SECTORS_PER_FAT]
337
    add   eax,[FAT_START]
338
    mov   [ROOT_START],eax      ; rootdir = fat_start + fat_size * fat_count
339
    add   eax,[ROOT_SECTORS]    ; rootdir sectors should be 0 on fat32
340
    mov   [DATA_START],eax      ; data area = rootdir + rootdir_size
341
 
342
    movzx eax,word [ebx+0x13]   ; total sector count <65536
343
    test  eax,eax
344
    jnz   fat16_total
345
    mov   eax,[ebx+0x20]        ; total sector count
346
  fat16_total:
347
    add   eax,[PARTITION_START]
348
    dec   eax
349
    mov   [PARTITION_END],eax
350
    inc   eax
351
    sub   eax,[DATA_START]      ; eax = count of data sectors
352
    xor   edx,edx
353
    div   dword [SECTORS_PER_CLUSTER]
354
    inc   eax
355
    mov   [LAST_CLUSTER],eax
356
    dec   eax                   ; cluster count
357
 
358
    ; limits by Microsoft Hardware White Paper v1.03
359
    cmp   eax,4085              ; 0xff5
360
    jb    problem_fat_dec_count ; fat12 not supported
361
    cmp   eax,65525             ; 0xfff5
362
    jb    fat16_partition
363
 
364
fat32_partition:
365
    mov   eax,[ebx+0x2c]        ; rootdir cluster
366
    mov   [ROOT_CLUSTER],eax
367
    movzx eax,word [ebx+0x30]   ; fs info sector
368
    add   eax,[PARTITION_START]
369
    mov   [ADR_FSINFO],eax
370
 
371
    popad
372
 
373
    mov   [fatRESERVED],0x0FFFFFF6
374
    mov   [fatBAD],0x0FFFFFF7
375
    mov   [fatEND],0x0FFFFFF8
376
    mov   [fatMASK],0x0FFFFFFF
377
    mov   [fat_type],32         ; Fat32
378
    mov   [hd1_status],0        ; free
379
    ret
380
 
381
fat16_partition:
382
    xor   eax,eax
383
    mov   [ROOT_CLUSTER],eax
384
 
385
    popad
386
 
387
    mov   [fatRESERVED],0x0000FFF6
388
    mov   [fatBAD],0x0000FFF7
389
    mov   [fatEND],0x0000FFF8
390
    mov   [fatMASK],0x0000FFFF
391
    mov   [fat_type],16         ; Fat16
392
    mov   [hd1_status],0        ; free
393
    ret
394
 
395
 
396
set_FAT:
397
;--------------------------------
398
; input  : EAX = cluster
399
;          EDX = value to save
400
; output : EDX = old value
401
;--------------------------------
402
    push  eax ebx esi
403
 
404
    cmp   eax,2
405
    jb    sfc_error
406
    cmp   eax,[LAST_CLUSTER]
407
    ja    sfc_error
408
    cmp   [fat_type],16
409
    je    sfc_1
410
    add   eax,eax
411
  sfc_1:
412
    add   eax,eax
413
    mov   esi,511
414
    and   esi,eax               ; esi = position in fat sector
415
    shr   eax,9                 ; eax = fat sector
416
    add   eax,[FAT_START]
417
    mov   ebx,fat_cache
418
 
419
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
420
    je    sfc_in_cache          ; yes
421
 
422
    cmp   [fat_change],0        ; is fat changed?
423
    je    sfc_no_change         ; no
424
    call  write_fat_sector      ; yes. write it into disk
425
 
426
  sfc_no_change:
427
    mov   [fat_in_cache],eax    ; save fat sector
428
    call  hd_read
429
 
430
  sfc_in_cache:
431
    cmp   [fat_type],16
432
    jne   sfc_test32
433
 
434
    cmp   [f_del],1             ; overwrite previous value?
435
    je    sfc_set16             ; yes
436
    cmp   word [ebx+esi],0      ; is cluster free?
437
    je    sfc_set16             ; yes
438
    mov   dword [8*0x100000],0xffffff
439
    mov   edx,[ebx+esi]         ; get old value
440
    jmp   sfc_nonzero
441
 
442
  sfc_set16:
443
    xchg  [ebx+esi],dx          ; save new value and get old value
444
    jmp   sfc_write
445
 
446
  sfc_test32:
447
    mov   eax,[fatMASK]
448
    cmp   [f_del],1             ; overwrite previous value?
449
    je    sfc_set32             ; yes
450
    test  eax,[ebx+esi]         ; is cluster free?
451
    je    sfc_set32             ; yes
452
    mov   dword [8*0x100000],0xffffff
453
    mov   edx,[ebx+esi]         ; get old value
454
    jmp   sfc_nonzero
455
 
456
  sfc_set32:
457
    and   edx,eax
458
    xor   eax,-1                ; mask for high bits
459
    and   eax,[ebx+esi]         ; get high 4 bits
460
    or    eax,edx
461
    mov   edx,[ebx+esi]         ; get old value
462
    mov   [ebx+esi],eax         ; save new value
463
 
464
  sfc_write:
465
    mov   [fat_change],1        ; fat has changed
466
 
467
  sfc_nonzero:
468
    and   edx,[fatMASK]
469
 
470
  sfc_error:
471
    pop   esi ebx eax
472
    ret
473
 
474
 
475
get_FAT:
476
;--------------------------------
477
; input  : EAX = cluster
478
; output : EAX = next cluster
479
;--------------------------------
480
    push  ebx esi
481
 
482
    cmp   [fat_type],16
483
    je    gfc_1
484
    add   eax,eax
485
  gfc_1:
486
    add   eax,eax
487
    mov   esi,511
488
    and   esi,eax               ; esi = position in fat sector
489
    shr   eax,9                 ; eax = fat sector
490
    add   eax,[FAT_START]
491
    mov   ebx,fat_cache
492
 
493
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
494
    je    gfc_in_cache
495
 
496
    cmp   [fat_change],0        ; is fat changed?
497
    je    gfc_no_change         ; no
498
    call  write_fat_sector      ; yes. write it into disk
499
 
500
  gfc_no_change:
501
    mov   [fat_in_cache],eax
502
    call  hd_read
503
 
504
  gfc_in_cache:
505
    mov   eax,[ebx+esi]
506
    and   eax,[fatMASK]
507
    pop   esi ebx
508
    ret
509
 
510
 
511
get_free_FAT:
512
;-----------------------------------------------------------
513
; input  : EAX = # cluster for start the searching
514
; output : if CARRY=0 EAX = # first cluster found free
515
;          if CARRY=1 disk full
516
; Note   : for more speed need to use fat_cache directly
517
;-----------------------------------------------------------
518
    push  ecx
519
    mov   ecx,[LAST_CLUSTER]    ; counter for full disk
520
    sub   ecx,2
521
 
522
  gff_test:
523
    cmp   eax,[LAST_CLUSTER]    ; if above last cluster start at cluster 2
524
    jbe   gff_in_range
525
    mov   eax,2
526
 
527
  gff_in_range:
528
    push  eax
529
    call  get_FAT               ; get cluster state
530
    test  eax,eax               ; is it free?
531
    pop   eax
532
    je    gff_found             ; yes
533
    inc   eax                   ; next cluster
534
    dec   ecx                   ; is all checked?
535
    jns   gff_test              ; no
536
 
537
  gff_not_found:
538
    pop   ecx                   ; yes. disk is full
539
    stc
540
    ret
541
 
542
  gff_found:
543
    pop   ecx
544
    clc
545
    ret
546
 
547
 
548
write_fat_sector:
549
;-----------------------------------------------------------
550
; write changed fat to disk
551
;-----------------------------------------------------------
552
    push  eax ebx ecx
553
 
554
    mov   [fat_change],0
555
    mov   eax,[fat_in_cache]
556
    cmp   eax,-1
557
    jz    write_fat_not_used
558
    mov   ebx,fat_cache
559
    mov   ecx,[NUMBER_OF_FATS]
560
 
561
  write_next_fat:
562
    call  hd_write
563
    add   eax,[SECTORS_PER_FAT]
564
    dec   ecx
565
    jnz   write_next_fat
566
 
567
  write_fat_not_used:
568
    pop   ecx ebx eax
569
    ret
570
 
571
 
572
analyze_directory:
573
;-----------------------------------------------------------
574
; input  : EAX = first cluster of the directory
575
;          EBX = pointer to filename
576
; output : IF CARRY=0 EAX = sector where th file is found
577
;                     EBX = pointer in buffer
578
;                     [buffer .. buffer+511]
579
;                     ECX,EDX,ESI,EDI not changed
580
;          IF CARRY=1 filename not found
581
; Note   : if cluster=0 it's changed to read rootdir
582
;          save 2 previous directory sectors in longname_sec
583
;-----------------------------------------------------------
584
    push  ecx edx esi edi ebx   ; ebx = [esp+0]
585
    mov   [longname_sec1],0
586
    mov   [longname_sec2],0
587
 
588
  adr_new_cluster:
589
    mov   [cluster_tmp],eax
590
    mov   [fat16_root],0
591
    cmp   eax,[LAST_CLUSTER]
592
    ja    adr_not_found         ; too big cluster number, something is wrong
593
    cmp   eax,2
594
    jnb   adr_data_cluster
595
 
596
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
597
    cmp   [fat_type],16
598
    jne   adr_data_cluster
599
    mov   eax,[ROOT_START]
600
    mov   edx,[ROOT_SECTORS]
601
    mov   [fat16_root],1        ; flag for fat16 rootdir
602
    jmp   adr_new_sector
603
 
604
  adr_data_cluster:
605
    sub   eax,2
606
    mov   edx,[SECTORS_PER_CLUSTER]
607
    imul  eax,edx
608
    add   eax,[DATA_START]
609
 
610
  adr_new_sector:
611
    mov   ebx,buffer
612
    call  hd_read
613
    mov   ecx,512/32            ; count of dir entrys per sector = 16
614
 
615
  adr_analyze:
616
    mov   edi,[ebx+11]          ; file attribute
617
    and   edi,0xf
618
    cmp   edi,0xf
619
    je    adr_long_filename
620
    test  edi,0x8               ; skip over volume label
621
    jne   adr_long_filename     ; Note: label can be same name as file/dir
622
 
623
    mov   esi,[esp+0]           ; filename need to be uppercase
624
    mov   edi,ebx
625
    push  ecx
626
    mov   ecx,11
627
    cld
628
    rep   cmpsb                 ; compare 8+3 filename
629
    pop   ecx
630
    je    adr_found
631
 
632
  adr_long_filename:
633
    add   ebx,32                ; position of next dir entry
634
    dec   ecx
635
    jnz   adr_analyze
636
 
637
    mov   ecx,[longname_sec1]   ; save 2 previous directory sectors
638
    mov   [longname_sec1],eax   ; for delete long filename
639
    mov   [longname_sec2],ecx
640
    inc   eax                   ; next sector
641
    dec   edx
642
    jne   adr_new_sector
643
    cmp   [fat16_root],1        ; end of fat16 rootdir
644
    je    adr_not_found
645
 
646
  adr_next_cluster:
647
    mov   eax,[cluster_tmp]
648
    call  get_FAT               ; get next cluster
649
    cmp   eax,2                 ; incorrect fat chain?
650
    jb    adr_not_found         ; yes
651
    cmp   eax,[fatRESERVED]     ; is it end of directory?
652
    jb    adr_new_cluster       ; no. analyse it
653
 
654
  adr_not_found:
655
    pop   edi edi esi edx ecx   ; first edi will remove ebx
656
    stc                         ; file not found
657
    ret
658
 
659
  adr_found:
660
    pop   edi edi esi edx ecx   ; first edi will remove ebx
661
    clc                         ; file found
662
    ret
663
 
664
 
665
analyze_directory_to_write:
666
;-----------------------------------------------------------
667
; input  : EAX = first cluster of the directory
668
; output : IF CARRY=0 EAX = sector where the empty pos is found
669
;                     EBX = pointer in buffer
670
;                     [buffer .. buffer+511]
671
;                     ECX,EDX,ESI,EDI not changed
672
;          IF CARRY=1 disk full or fat corrupted
673
; Note   : if cluster=0 it's changed to read rootdir
674
;-----------------------------------------------------------
675
    push  ecx edx edi
676
 
677
  adw_new_cluster:
678
    mov   [cluster_tmp],eax
679
    mov   [fat16_root],0
680
    cmp   eax,[LAST_CLUSTER]
681
    ja    adw_not_found         ; too big cluster number, something is wrong
682
    cmp   eax,2
683
    jnb   adw_data_cluster
684
 
685
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
686
    cmp   [fat_type],16
687
    jne   adw_data_cluster
688
    mov   eax,[ROOT_START]
689
    mov   edx,[ROOT_SECTORS]
690
    mov   [fat16_root],1        ; flag for fat16 rootdir
691
    jmp   adw_new_sector
692
 
693
  adw_data_cluster:
694
    sub   eax,2
695
    mov   edx,[SECTORS_PER_CLUSTER]
696
    imul  eax,edx
697
    add   eax,[DATA_START]
698
 
699
  adw_new_sector:
700
    mov   ebx,buffer
701
    call  hd_read
702
    mov   ecx,512/32            ; count of dir entrys per sector = 16
703
 
704
  adw_analyze:
705
    cmp   byte [ebx],0x00       ; is free entry?
706
    je    adw_found             ; yes
707
    cmp   byte [ebx],0xe5       ; is deleted entry?
708
    je    adw_found             ; yes
709
    add   ebx,32                ; position of next dir entry
710
    dec   ecx
711
    jnz   adw_analyze
712
 
713
    inc   eax                   ; next sector
714
    dec   edx
715
    jne   adw_new_sector
716
    cmp   [fat16_root],1        ; end of fat16 rootdir
717
    je    adw_not_found
718
 
719
    mov   eax,[cluster_tmp]
720
    call  get_FAT               ; get next cluster
721
    cmp   eax,2                 ; incorrect fat chain?
722
    jb    adw_not_found         ; yes
723
    cmp   eax,[fatRESERVED]     ; is it end of directory?
724
    jb    adw_new_cluster       ; no. analyse it
725
 
726
    mov   eax,2                 ; this block of code add a new cluster
727
    call  get_free_FAT          ; for the directory because the directory
728
    jc    adw_not_found         ; is full
729
 
730
    mov   edx,[fatEND]          ; new end for directory
731
    call  set_FAT
732
 
733
    push  eax                   ; save new cluster
734
    mov   edx,eax
735
    mov   eax,[cluster_tmp]     ; change last cluster to point new cluster
736
    mov   [f_del],1
737
    call  set_FAT
738
    mov   [f_del],0
739
 
740
    mov   ecx,-1                ; remove 1 cluster from free disk space
741
    call  add_disk_free_space
742
 
743
    mov   ecx,512/4
744
    xor   eax,eax
745
    mov   edi,buffer
746
    cld
747
    rep   stosd                 ; clear new directory cluster
748
    pop   eax
749
 
750
    sub   eax,2
751
    mov   ecx,[SECTORS_PER_CLUSTER]
752
    imul  eax,ecx
753
    add   eax,[DATA_START]
754
    mov   ebx,buffer
755
    push  eax                   ; save sector number
756
 
757
  adw_set_empty_directory:
758
    call  hd_write
759
    inc   eax                   ; next sector
760
    dec   ecx
761
    jnz   adw_set_empty_directory
762
 
763
    pop   eax
764
 
765
  adw_found:
766
    pop   edi edx ecx
767
    clc                         ; free space found
768
    ret
769
 
770
  adw_not_found:
771
    pop   edi edx ecx
772
    stc                         ; free space not found
773
    ret
774
 
775
 
776
get_data_cluster:
777
;-----------------------------------------------------------
778
; input  : EAX = cluster
779
;          EBX = pointer to buffer
780
;          EDX = # blocks to read in buffer
781
;          ESI = # blocks to skip over
782
; output : if CARRY=0 ok EBX/EDX/ESI updated
783
;          if CARRY=1 cluster out of range
784
; Note   : if cluster=0 it's changed to read rootdir
785
;-----------------------------------------------------------
786
    push  eax ecx
787
 
788
    mov   [fat16_root],0
789
    cmp   eax,[LAST_CLUSTER]
790
    ja    gdc_error             ; too big cluster number, something is wrong
791
    cmp   eax,2
792
    jnb   gdc_cluster
793
 
794
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
795
    cmp   [fat_type],16
796
    jne   gdc_cluster
797
    mov   eax,[ROOT_START]
798
    mov   ecx,[ROOT_SECTORS]    ; Note: not cluster size
799
    mov   [fat16_root],1        ; flag for fat16 rootdir
800
    jmp   gdc_read
801
 
802
  gdc_cluster:
803
    sub   eax,2
804
    mov   ecx,[SECTORS_PER_CLUSTER]
805
    imul  eax,ecx
806
    add   eax,[DATA_START]
807
 
808
  gdc_read:
809
    test  esi,esi               ; first wanted block
810
    je    gdcl1                 ; yes, skip count is 0
811
    dec   esi
812
    jmp   gdcl2
813
 
814
  gdcl1:
815
    call  hd_read
816
    add   ebx,512               ; update pointer
817
    dec   edx
818
 
819
  gdcl2:
820
    test  edx,edx               ; is all read?
821
    je    out_of_read
822
 
823
    inc   eax                   ; next sector
824
    dec   ecx
825
    jnz   gdc_read
826
 
827
  out_of_read:
828
    pop   ecx eax
829
    clc
830
    ret
831
 
832
  gdc_error:
833
    pop   ecx eax
834
    stc
835
    ret
836
 
837
 
838
set_data_cluster:
839
;-----------------------------------------------------------
840
; input  : EAX = cluster
841
;          EBX = pointer to buffer
842
; output : if CARRY=0 ok
843
;          if CARRY=1 cluster out of range
844
;-----------------------------------------------------------
845
    push  eax ebx edx
846
 
847
    cmp   eax,[LAST_CLUSTER]
848
    ja    sdc_error             ; too big cluster number, something is wrong
849
    sub   eax,2
850
    jb    sdc_error             ; don't allow rootdir write
851
 
852
    mov   edx,[SECTORS_PER_CLUSTER]
853
    imul  eax,edx
854
    add   eax,[DATA_START]
855
 
856
  sdc_write:
857
    call  hd_write
858
    add   ebx,512               ; update pointer
859
    inc   eax
860
    dec   edx
861
    jnz   sdc_write
862
    pop   edx ebx eax
863
    clc
864
    ret
865
 
866
  sdc_error:
867
    pop   edx ebx eax
868
    stc
869
    ret
870
 
871
 
872
get_cluster_of_a_path:
873
;---------------------------------------------------------
874
; input  : EBX = pointer to a path string
875
;          (example: the path "/files/data/document" become
876
;                             "files......data.......document...0"
877
;          '.' = space char
878
;          '0' = char(0) (ASCII=0) !!! )
879
; output : if (CARRY=1) -> ERROR in the PATH
880
;          if (CARRY=0) -> EAX=cluster
881
;---------------------------------------------------------
882
    push  ebx edx
883
 
884
    mov   eax,[ROOT_CLUSTER]
885
    mov   edx,ebx
886
 
887
search_end_of_path:
888
    cmp   byte [edx],0
889
    je    found_end_of_path
890
 
891
    inc   edx ; '/'
892
    mov   ebx,edx
893
    call  analyze_directory
894
    jc    directory_not_found
895
 
896
    mov   eax,[ebx+20-2]        ; read the HIGH 16bit cluster field
897
    mov   ax,[ebx+26]           ; read the LOW 16bit cluster field
898
    and   eax,[fatMASK]
899
    add   edx,11                ; 8+3 (name+extension)
900
    jmp   search_end_of_path
901
 
902
found_end_of_path:
903
    pop   edx ebx
904
    clc                         ; no errors
905
    ret
906
 
907
directory_not_found:
908
    pop   edx ebx
909
    stc                         ; errors occour
910
    ret
911
 
912
 
913
bcd2bin:
914
;----------------------------------
915
; input  : AL=BCD number (eg. 0x11)
916
; output : AH=0
917
;          AL=decimal number (eg. 11)
918
;----------------------------------
919
    xor   ah,ah
920
    shl   ax,4
921
    shr   al,4
922
    aad
923
    ret
924
 
925
 
926
get_date_for_file:
927
;-----------------------------------------------------
928
; Get date from CMOS and pack day,month,year in AX
929
; DATE   bits  0..4   : day of month 0..31
930
;              5..8   : month of year 1..12
931
;              9..15  : count of years from 1980
932
;-----------------------------------------------------
933
    mov   al,0x7        ;day
934
    out   0x70,al
935
    in    al,0x71
936
    call  bcd2bin
937
    ror   eax,5
938
 
939
    mov   al,0x8        ;month
940
    out   0x70,al
941
    in    al,0x71
942
    call  bcd2bin
943
    ror   eax,4
944
 
945
    mov   al,0x9        ;year
946
    out   0x70,al
947
    in    al,0x71
948
    call  bcd2bin
949
    add   ax,20         ;because CMOS return only the two last
950
                        ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
951
    rol   eax,9         ;need the difference with 1980 (eg. 2001-1980)
952
    ret
953
 
954
 
955
get_time_for_file:
956
;-----------------------------------------------------
957
; Get time from CMOS and pack hour,minute,second in AX
958
; TIME   bits  0..4   : second (the low bit is lost)
959
;              5..10  : minute 0..59
960
;              11..15 : hour 0..23
961
;-----------------------------------------------------
962
    mov   al,0x0        ;second
963
    out   0x70,al
964
    in    al,0x71
965
    call  bcd2bin
966
    ror   eax,6
967
 
968
    mov   al,0x2        ;minute
969
    out   0x70,al
970
    in    al,0x71
971
    call  bcd2bin
972
    ror   eax,6
973
 
974
    mov   al,0x4        ;hour
975
    out   0x70,al
976
    in    al,0x71
977
    call  bcd2bin
978
    rol   eax,11
979
    ret
980
 
981
 
982
set_current_time_for_entry:
983
;-----------------------------------------------------
984
; Set current time/date for file entry
985
; input  : ebx = file entry pointer
986
;-----------------------------------------------------
987
    push  eax
988
    call  get_time_for_file     ; update files date/time
989
    mov   [ebx+22],ax
990
    call  get_date_for_file
991
    mov   [ebx+24],ax
992
    pop   eax
993
    ret
994
 
995
 
996
makedir:
997
;-----------------------------------------------------
998
; input  : eax = directory name
999
;          edx = path
1000
; output : eax = 0 - ok
1001
;                3 - unknown FS
1002
;                5 - file not found
1003
;                8 - disk full
1004
;               10 - access denied
1005
; Note   : can only make one directory at time
1006
;-----------------------------------------------------
1007
    cmp   [fat_type],0
1008
    jnz   make_dir_fat_ok
1009
    mov   eax,ERROR_UNKNOWN_FS
1010
    ret
1011
 
1012
  make_dir_fat_ok:
1013
;    call  reserve_hd1
1014
 
1015
    pushad
1016
 
1017
    mov   ebx,edx
1018
    call  get_cluster_of_a_path
1019
    jnc   make_dir_found_path
1020
 
1021
  make_dir_path_not_found:
1022
    popad
1023
    call  update_disk           ; write all of cache and fat to hd
1024
    mov   [hd1_status],0
1025
    mov   eax,ERROR_FILE_NOT_FOUND
1026
    ret
1027
 
1028
  make_dir_disk_full:
1029
    popad
1030
    call  update_disk           ; write all of cache and fat to hd
1031
    mov   [hd1_status],0
1032
    mov   eax,ERROR_DISK_FULL
1033
    ret
1034
 
1035
  make_dir_already_exist:
1036
    mov   eax,[cluster]         ; directory cluster
1037
    xor   edx,edx               ; free
1038
    mov   [f_del],1
1039
    call  set_FAT
1040
    mov   [f_del],0
1041
 
1042
    popad
1043
    call  update_disk           ; write all of cache and fat to hd
1044
    mov   [hd1_status],0
1045
    mov   eax,ERROR_ACCESS_DENIED
1046
    ret
1047
 
1048
  make_dir_found_path:
1049
    cmp   eax,[ROOT_CLUSTER]
1050
    jnz   make_dir_not_root
1051
    xor   eax,eax
1052
 
1053
  make_dir_not_root:
1054
    mov   ecx,eax               ; directorys start cluster
1055
    mov   word [NewDirEntry2+26],cx ; 16 bits low of cluster
1056
    shr   ecx,16
1057
    mov   word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16)
1058
 
1059
    push  eax                   ; save parent directory cluster
1060
    mov   eax,2
1061
    call  get_free_FAT
1062
    mov   [cluster],eax         ; first free cluster
1063
    pop   eax
1064
    jc    make_dir_disk_full
1065
 
1066
    push  eax
1067
    mov   eax,[cluster]         ; directory cluster
1068
    mov   edx,[fatEND]          ; end for directory
1069
    call  set_FAT
1070
    pop   eax
1071
 
1072
    mov   ebx,PUSHAD_EAX        ; dir name
1073
    push  eax
1074
    call  analyze_directory     ; check if directory already exist
1075
    pop   eax
1076
    jnc   make_dir_already_exist ; need to free allocated cluster!
1077
 
1078
    call  analyze_directory_to_write
1079
    jc    make_dir_already_exist ; need to free allocated cluster!
1080
 
1081
    mov   esi,PUSHAD_EAX        ; dir name
1082
    mov   edi,ebx               ; pointer in buffer
1083
    mov   ecx,11
1084
    cld
1085
    rep   movsb
1086
 
1087
    mov   dword [ebx+28],0      ; dir size is always 0
1088
    mov   ecx,[cluster]
1089
    mov   [ebx+26],cx           ; 16 bits low of cluster
1090
    mov   word [NewDirEntry1+26],cx
1091
    shr   ecx,16
1092
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
1093
    mov   word [NewDirEntry1+20],cx
1094
    mov   byte [ebx+11],0x10    ; attribute = directory
1095
 
1096
    call  set_current_time_for_entry
1097
    mov   ecx,[ebx+22]
1098
    mov   dword [NewDirEntry1+22],ecx
1099
    mov   dword [NewDirEntry2+22],ecx
1100
 
1101
    mov   ebx,buffer            ; save the directory name,length,cluster
1102
    call  hd_write
1103
 
1104
    mov   ecx,512/4
1105
    xor   eax,eax
1106
    mov   edi,buffer
1107
    cld
1108
    rep   stosd                 ; clear new directory cluster
1109
 
1110
    mov   eax,[cluster]         ; new directory cluster
1111
    sub   eax,2
1112
    mov   edx,[SECTORS_PER_CLUSTER]
1113
    imul  eax,edx
1114
    add   eax,[DATA_START]
1115
    mov   ebx,buffer
1116
    add   eax,edx               ; start from last sector
1117
 
1118
  dir_set_empty_directory:
1119
    dec   eax                   ; next sector
1120
    cmp   edx,1                 ; is first directory sector?
1121
    jnz   not_first_sector      ; no. write empty sector
1122
    mov   esi,NewDirEntry1
1123
    mov   edi,buffer
1124
    mov   ecx,64/4
1125
    cld
1126
    rep   movsd                 ; copy 2 first directory entrys "." and ".."
1127
 
1128
  not_first_sector:
1129
    call  hd_write
1130
    dec   edx
1131
    jnz   dir_set_empty_directory
1132
 
1133
    mov   ecx,-1                ; remove 1 cluster from free disk space
1134
    call  add_disk_free_space
1135
 
1136
    popad
1137
    call  update_disk           ; write all of cache and fat to hd
1138
    mov   [hd1_status],0
1139
    xor   eax,eax
1140
    ret
1141
 
1142
 
1143
removedir:
1144
;-----------------------------------------------------
1145
; input  : eax = file/directory name
1146
;          edx = path
1147
; output : eax = 0 - ok
1148
;                3 - unknown FS
1149
;                5 - file not found
1150
;               10 - access denied
1151
;-----------------------------------------------------
1152
    cmp   [fat_type],0
1153
    jnz   remove_dir_fat_ok
1154
    mov   eax,ERROR_UNKNOWN_FS
1155
    ret
1156
 
1157
  remove_dir_fat_ok:
1158
;    call  reserve_hd1
1159
 
1160
    push  edi
1161
    mov   edi,1                 ; allow directory remove
1162
    call  file_delete
1163
    pop   edi
1164
 
1165
    call  update_disk           ; write all of cache and fat to hd
1166
    mov   [hd1_status],0
1167
    ret
1168
 
1169
 
1170
add_disk_free_space:
1171
;-----------------------------------------------------
1172
; input  : ecx = cluster count
1173
; Note   : negative = remove clusters from free space
1174
;          positive = add clusters to free space
1175
;-----------------------------------------------------
1176
    test  ecx,ecx               ; no change
1177
    je    add_dfs_no
1178
    cmp   [fat_type],32         ; free disk space only used by fat32
1179
    jne   add_dfs_no
1180
 
1181
    push  eax ebx
1182
    mov   eax,[ADR_FSINFO]
1183
    mov   ebx,buffer
1184
    call  hd_read
1185
    cmp   dword [ebx+0x1fc],0xaa550000 ; check sector id
1186
    jne   add_not_fs
1187
 
1188
    add   [ebx+0x1e8],ecx
1189
    call  hd_write
1190
 
1191
  add_not_fs:
1192
    pop   ebx eax
1193
 
1194
  add_dfs_no:
1195
    ret
1196
 
1197
 
1198
file_append:
1199
;-----------------------------------------------------
1200
; input  : eax = file name
1201
;          edx = path
1202
;          ecx = pointer to buffer
1203
;          ebx = bytes to write (0 = truncate file)
1204
;          esi = start position (-1 = end of file)
1205
; output : eax = 0 - ok
1206
;                3 - unknown FS
1207
;                5 - file not found
1208
;                6 - end of file
1209
;                8 - disk full
1210
;                9 - fat table corrupted
1211
;               10 - access denied
1212
;          ebx = bytes written
1213
;-----------------------------------------------------
1214
    cmp   [fat_type],0
1215
    jnz   append_fat_ok
1216
    mov   eax,ERROR_UNKNOWN_FS
1217
    ret
1218
 
1219
  append_fat_ok:
1220
;    call  reserve_hd1
1221
 
1222
    pushad
1223
 
1224
    mov   ebx,edx
1225
    call  get_cluster_of_a_path
1226
    jc    append_not_found
1227
 
1228
    mov   ebx,PUSHAD_EAX        ; file name
1229
    call  analyze_directory
1230
    jc    append_not_found
1231
 
1232
    mov   [sector_tmp],eax
1233
    mov   [entry_pos],ebx
1234
 
1235
    test  byte [ebx+11],0x10    ; is it directory?
1236
    jnz   append_access         ; yes
1237
 
1238
    mov   ecx,[ebx+28]          ; file size
1239
    mov   edi,PUSHAD_ESI        ; write position
1240
    cmp   edi,-1                ; -1 = eof
1241
    jnz   append_inside_file
1242
    mov   edi,ecx               ; file size
1243
 
1244
  append_inside_file:
1245
    cmp   edi,ecx               ; start above old file size?
1246
    ja    append_eof            ; yes
1247
 
1248
    mov   [old_filesize],ecx
1249
    mov   [new_filepos],edi
1250
 
1251
    mov   ecx,PUSHAD_EBX        ; bytes to write
1252
    test  ecx,ecx               ; truncate?
1253
    jz    append_truncate       ; yes
1254
 
1255
    mov   [bytes2write],ecx     ; bytes to write
1256
    mov   esi,PUSHAD_ECX        ; pointer to buffer
1257
    mov   eax,[ebx+20-2]        ; FAT entry
1258
    mov   ax,[ebx+26]
1259
    and   eax,[fatMASK]
1260
    jnz   append_find_pos       ; first cluster <> 0
1261
 
1262
    mov   eax,2
1263
    call  get_free_FAT
1264
    jc    append_disk_full
1265
    mov   ecx,eax               ; set files first cluster
1266
    mov   [ebx+26],cx           ; 16 bits low of cluster
1267
    shr   ecx,16
1268
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
1269
    mov   edx,[fatEND]          ; new end for cluster chain
1270
    call  set_FAT
1271
 
1272
    push  eax                   ; save first cluster
1273
    mov   eax,[sector_tmp]
1274
    mov   ebx,buffer
1275
    call  hd_write              ; write new file entry back to disk
1276
    pop   eax
1277
 
1278
  append_remove_free:
1279
    mov   ecx,-1                ; remove 1 cluster from free disk space
1280
    call  add_disk_free_space   ; Note: uses buffer
1281
 
1282
  append_found_cluster:
1283
    mov   [cluster],eax
1284
    sub   eax,2
1285
    mov   ecx,[SECTORS_PER_CLUSTER]
1286
    imul  eax,ecx
1287
    add   eax,[DATA_START]
1288
    xor   edi,edi
1289
 
1290
  append_new_sector:
1291
    push  ecx
1292
    mov   ecx,[bytes2write]     ; bytes left in buffer
1293
    mov   ebx,512
1294
    sub   ebx,edi               ; bytes left in sector
1295
    cmp   ecx,ebx
1296
    jb    append_bytes_ok
1297
    mov   ecx,ebx
1298
 
1299
  append_bytes_ok:
1300
    cmp   ecx,512               ; overwrite full sector?
1301
    jz    append_full_sector    ; yes
1302
    mov   ebx,buffer            ; overwrite part of sector
1303
    call  hd_read               ; read old sector
1304
 
1305
  append_full_sector:
1306
    sub   [bytes2write],ecx
1307
    add   [new_filepos],ecx
1308
    add   edi,buffer
1309
    cld
1310
    rep   movsb
1311
    pop   ecx
1312
 
1313
    mov   ebx,buffer
1314
    call  hd_write
1315
    cmp   [bytes2write],0       ; is all done?
1316
    jz    append_done
1317
    xor   edi,edi
1318
    inc   eax
1319
    dec   ecx
1320
    jnz   append_new_sector
1321
 
1322
    mov   eax,[cluster]
1323
    call  get_FAT
1324
    cmp   eax,2
1325
    jb    append_fat
1326
    cmp   eax,[LAST_CLUSTER]
1327
    jbe   append_found_cluster
1328
 
1329
  append_alloc_cluster:
1330
    mov   eax,2                 ; ToDo: use temp array to keep track
1331
    call  get_free_FAT          ;       of last free cluster
1332
    jc    append_disk_full
1333
    push  eax                   ; save new cluster
1334
    mov   edx,[fatEND]          ; new end for cluster chain
1335
    call  set_FAT
1336
    mov   edx,eax
1337
    mov   eax,[cluster]
1338
    mov   [f_del],1
1339
    call  set_FAT               ; update previous cluster
1340
    mov   [f_del],0
1341
    pop   eax
1342
    jmp   append_remove_free
1343
 
1344
  append_find_pos:
1345
    call  find_filepos
1346
    mov   [cluster],ebx
1347
    jnc   append_new_sector
1348
    test  edi,edi
1349
    jz    append_alloc_cluster
1350
 
1351
  append_fat:
1352
    mov   eax,ERROR_FAT_TABLE
1353
    jmp   append_ret_code
1354
 
1355
  append_disk_full:
1356
    mov   eax,ERROR_DISK_FULL
1357
    jmp   append_ret_code
1358
 
1359
  append_done:
1360
    xor   eax,eax
1361
 
1362
  append_ret_code:
1363
    mov   PUSHAD_EAX,eax        ; return code
1364
 
1365
    mov   eax,[sector_tmp]      ; update directory entry
1366
    mov   ebx,buffer
1367
    call  hd_read
1368
    mov   ebx,[entry_pos]
1369
    mov   ecx,[new_filepos]
1370
    cmp   ecx,[old_filesize]    ; is file pos above old size?
1371
    jbe   append_size_ok        ; no
1372
    mov   [ebx+28],ecx          ; new file size
1373
 
1374
  append_size_ok:
1375
    call  set_current_time_for_entry
1376
    mov   ebx,buffer
1377
    call  hd_write              ; write new file entry back to disk
1378
 
1379
    sub   ecx,PUSHAD_ESI        ; start position
1380
    mov   PUSHAD_EBX,ecx        ; bytes written
1381
    popad
1382
    call  update_disk           ; write all of cache and fat to hd
1383
    mov   [hd1_status],0
1384
    ret
1385
 
1386
  append_eof:
1387
    popad
1388
    mov   [hd1_status],0
1389
    xor   ebx,ebx
1390
    mov   eax,ERROR_END_OF_FILE
1391
    ret
1392
 
1393
  append_not_found:
1394
    popad
1395
    mov   [hd1_status],0
1396
    xor   ebx,ebx
1397
    mov   eax,ERROR_FILE_NOT_FOUND
1398
    ret
1399
 
1400
  append_access:
1401
    popad
1402
    mov   [hd1_status],0
1403
    xor   ebx,ebx
1404
    mov   eax,ERROR_ACCESS_DENIED
1405
    ret
1406
 
1407
  append_truncate:
1408
    mov   edx,[ebx+20-2]        ; FAT entry
1409
    mov   dx,[ebx+26]
1410
    and   edx,[fatMASK]
1411
    mov   [ebx+28],edi          ; set new file size
1412
    test  edi,edi               ; 0 length file?
1413
    jnz   truncate_save_size    ; no
1414
    mov   [ebx+20],di           ; FAT entry = 0
1415
    mov   [ebx+26],di
1416
 
1417
  truncate_save_size:
1418
    call  set_current_time_for_entry
1419
    mov   ebx,buffer
1420
    call  hd_write
1421
    mov   eax,edx               ; first cluster
1422
    test  edi,edi               ; 0 length file?
1423
    jz    truncate_clear_chain
1424
 
1425
    imul  esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes
1426
 
1427
  truncate_new_cluster:
1428
    cmp   eax,2                 ; incorrect fat chain?
1429
    jb    truncate_eof          ; yes
1430
    cmp   eax,[fatRESERVED]     ; is it end of file?
1431
    jnb   truncate_eof          ; yes
1432
    sub   edi,esi
1433
    jbe   truncate_pos_found
1434
    call  get_FAT               ; get next cluster
1435
    jmp   truncate_new_cluster
1436
 
1437
  truncate_pos_found:
1438
    mov   edx,[fatEND]          ; new end for cluster chain
1439
    mov   [f_del],1
1440
    call  set_FAT
1441
    mov   [f_del],0
1442
    mov   eax,edx               ; clear rest of chain
1443
 
1444
  truncate_clear_chain:
1445
    call  clear_cluster_chain
1446
 
1447
  truncate_eof:
1448
    popad
1449
    call  update_disk           ; write all of cache and fat to hd
1450
    mov   [hd1_status],0
1451
    xor   ebx,ebx
1452
    xor   eax,eax
1453
    ret
1454
 
1455
 
1456
find_filepos:
1457
;-----------------------------------------------------
1458
; input  : eax = first cluster
1459
;          edi = bytes to skip over (start position)
1460
; output : if CARRY=0 file position found
1461
;          if CARRY=1 end of file found
1462
;          eax = current file sector
1463
;          ebx = last cluster
1464
;          ecx = sector count in last cluster
1465
;          edi = bytes to skip over (sector position)
1466
;-----------------------------------------------------
1467
    push  esi
1468
    mov   ecx,[SECTORS_PER_CLUSTER]
1469
    imul  esi,ecx,512           ; esi = cluster size in bytes
1470
    mov   ebx,eax
1471
 
1472
  filepos_new_cluster:
1473
    cmp   eax,2                 ; incorrect fat chain?
1474
    jb    filepos_eof           ; yes
1475
    cmp   eax,[fatRESERVED]     ; is it end of file?
1476
    jnb   filepos_eof           ; yes
1477
 
1478
    mov   ebx,eax
1479
    cmp   edi,esi               ; skip over full cluster?
1480
    jb    filepos_cluster_ok    ; no
1481
 
1482
    sub   edi,esi
1483
    call  get_FAT               ; get next cluster
1484
    jmp   filepos_new_cluster
1485
 
1486
  filepos_cluster_ok:
1487
    sub   eax,2
1488
    imul  eax,ecx
1489
    add   eax,[DATA_START]
1490
 
1491
  filepos_new_sector:
1492
    cmp   edi,512               ; skip over full sector?
1493
    jb    filepos_sector_ok     ; no
1494
    sub   edi,512
1495
    inc   eax
1496
    dec   ecx
1497
    jnz   filepos_new_sector
1498
 
1499
  filepos_eof:
1500
    pop   esi
1501
    stc
1502
    ret
1503
 
1504
  filepos_sector_ok:
1505
    pop   esi
1506
    clc
1507
    ret
1508
 
1509
 
1510
file_write:
1511
;--------------------------------------------------------------------------
1512
;   INPUT : user-reg  register-in-this  meaning      symbol-in-this-routine
1513
;
1514
;            EAX        EDI            system call to write    /
1515
;            EBX        EAX   (PAR0)   pointer to file-name    PAR0
1516
;            EDX        ECX   (PAR1)   pointer to buffer       PAR1
1517
;            ECX        EBX   (PAR2)   file size               PAR2
1518
;            ESI        EDX   (PAR3)   pointer to path         PAR3
1519
;
1520
; output : eax = 0 - ok
1521
;                3 - unknown FS
1522
;                5 - file not found
1523
;                8 - disk full
1524
;               10 - access denied
1525
;--------------------------------------------------------------------------
1526
    cmp   [fat_type],0
1527
    jnz   fat_ok_for_writing
1528
    mov   eax,ERROR_UNKNOWN_FS
1529
    ret
1530
 
1531
  fat_ok_for_writing:
1532
;    call  reserve_hd1
1533
 
1534
    pushad
1535
 
1536
    xor   edi,edi               ; don't allow directory remove
1537
    call  file_delete           ; try to delete the file first
1538
    test  eax,eax
1539
    jz    old_deleted           ; deleted ok
1540
    cmp   eax,ERROR_FILE_NOT_FOUND
1541
    jnz   exit_write_access     ; it exist but can't delete
1542
 
1543
  old_deleted:
1544
    mov   ebx,PUSHAD_EDX
1545
    call  get_cluster_of_a_path
1546
    jnc   found_directory_for_writing
1547
 
1548
  exit_writing_with_error:
1549
    popad
1550
    call  update_disk           ; write all of cache and fat to hd
1551
    mov   [hd1_status],0
1552
    mov   eax,ERROR_FILE_NOT_FOUND
1553
    ret
1554
 
1555
  exit_writing_disk_full_clear:
1556
    mov   eax,[sector_tmp]
1557
    mov   ebx,buffer
1558
    call  hd_read               ; read directory sector
1559
    mov   edx,[entry_pos]
1560
    mov   byte [edx],0xe5       ; mark as deleted
1561
    call  hd_write
1562
    mov   eax,[edx+20-2]        ; FAT entry
1563
    mov   ax,[edx+26]
1564
    and   eax,[fatMASK]
1565
    call  clear_cluster_chain
1566
 
1567
  exit_writing_disk_full:
1568
    popad
1569
    call  update_disk           ; write all of cache and fat to hd
1570
    mov   [hd1_status],0
1571
    mov   eax,ERROR_DISK_FULL
1572
    ret
1573
 
1574
  exit_write_access:
1575
    popad
1576
    call  update_disk           ; write all of cache and fat to hd
1577
    mov   [hd1_status],0
1578
    mov   eax,ERROR_ACCESS_DENIED
1579
    ret
1580
 
1581
found_directory_for_writing:
1582
    call  analyze_directory_to_write
1583
    jc    exit_writing_disk_full
1584
 
1585
    mov   [sector_tmp],eax
1586
    mov   [entry_pos],ebx
1587
    push  eax                   ; save directory sector
1588
    mov   eax,2
1589
    call  get_free_FAT
1590
    mov   [cluster],eax         ; first free cluster
1591
    pop   eax
1592
    jc    exit_writing_disk_full
1593
 
1594
    mov   esi,PUSHAD_EAX        ; file name
1595
    mov   edi,ebx               ; pointer in buffer
1596
    mov   ecx,11
1597
    cld
1598
    rep   movsb
1599
 
1600
    mov   esi,PUSHAD_EBX        ; file size (bytes left)
1601
    mov   [ebx+28],esi          ; file size
1602
    mov   ecx,[cluster]
1603
    mov   [ebx+26],cx           ; 16 bits low of cluster
1604
    shr   ecx,16
1605
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
1606
    mov   byte [ebx+11],0x20    ; attribute = archive
1607
 
1608
    call  set_current_time_for_entry
1609
 
1610
    mov   ebx,buffer            ; save the directory name,length,cluster
1611
    call  hd_write
1612
 
1613
    imul  edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes
1614
    xor   ecx,ecx               ; cluster count
1615
    mov   ebx,PUSHAD_ECX        ; ebx = buffer
1616
 
1617
hd_new_block_write:
1618
 
1619
    mov   eax,[cluster]         ; eax = block
1620
    call  set_data_cluster
1621
 
1622
    sub   esi,edi               ; sub wrote bytes
1623
    jbe   file_saved_OK         ; end if all done
1624
    add   ebx,edi               ; update buffer position
1625
 
1626
    inc   eax
1627
    call  get_free_FAT          ; next free in FAT
1628
    jc    exit_writing_disk_full_clear
1629
 
1630
    mov   edx,eax
1631
    xchg  eax,[cluster]         ; get old cluster and save new cluster
1632
    call  set_FAT               ; add it in cluster chain
1633
    dec   ecx                   ; update cluster count
1634
    jmp   hd_new_block_write
1635
 
1636
file_saved_OK:
1637
 
1638
    mov   edx,[fatEND]          ; new end for cluster chain
1639
    call  set_FAT
1640
    dec   ecx                   ; update cluster count
1641
 
1642
    call  add_disk_free_space   ; remove clusters from free disk space
1643
 
1644
    popad
1645
    call  update_disk           ; write all of cache and fat to hd
1646
    mov   [hd1_status],0
1647
    xor   eax,eax
1648
    ret
1649
 
1650
 
1651
file_read:
1652
;--------------------------------------------------------------------------
1653
;   INPUT :  user-register register-in-this  meaning         symbol-in-this
1654
;
1655
;            EAX           EDI               system call to write   /
1656
;            EBX           EAX   (PAR0)      pointer to file-name   PAR0
1657
;            EDX           ECX   (PAR1)      pointer to buffer      PAR1
1658
;            ECX           EBX   (PAR2)   vt file blocks to read    PAR2
1659
;            ESI           EDX   (PAR3)      pointer to path        PAR3
1660
;            EDI           ESI            vt first 512 block to read
1661
;                          EDI               if 0 - read root
1662
;
1663
; output : eax = 0 - ok
1664
;                3 - unknown FS
1665
;                5 - file not found
1666
;                6 - end of file
1667
;                9 - fat table corrupted
1668
;          ebx = size of file/directory
1669
;--------------------------------------------------------------------------
1670
    cmp   [fat_type],0
1671
    jnz   fat_ok_for_reading
1672
    xor   ebx,ebx
1673
    mov   eax,ERROR_UNKNOWN_FS
1674
    ret
1675
 
1676
  fat_ok_for_reading:
1677
;    call  reserve_hd1
1678
 
1679
    pushad
1680
 
1681
    mov   ebx,edx
1682
    call  get_cluster_of_a_path
1683
    jc    file_to_read_not_found
1684
 
1685
    test  edi,edi               ; read rootdir
1686
    jne   no_read_root
1687
 
1688
    xor   eax,eax
1689
    call  get_dir_size          ; return rootdir size
1690
    mov   [file_size],eax
1691
    mov   eax,[ROOT_CLUSTER]
1692
    jmp   file_read_start
1693
 
1694
  no_read_root:
1695
    mov   ebx,PUSHAD_EAX        ; file name
1696
    call  analyze_directory
1697
    jc    file_to_read_not_found
1698
 
1699
    mov   eax,[ebx+28]          ; file size
1700
    test  byte [ebx+11],0x10    ; is it directory?
1701
    jz    read_set_size         ; no
1702
 
1703
    mov   eax,[ebx+20-2]        ; FAT entry
1704
    mov   ax,[ebx+26]
1705
    and   eax,[fatMASK]
1706
    call  get_dir_size
1707
 
1708
  read_set_size:
1709
    mov   [file_size],eax
1710
 
1711
    mov   eax,[ebx+20-2]        ; FAT entry
1712
    mov   ax,[ebx+26]
1713
    and   eax,[fatMASK]
1714
 
1715
  file_read_start:
1716
    mov   ebx,PUSHAD_ECX        ; pointer to buffer
1717
    mov   edx,PUSHAD_EBX        ; file blocks to read
1718
    mov   esi,PUSHAD_ESI        ; first 512 block to read
1719
 
1720
  file_read_new_cluster:
1721
    call  get_data_cluster
1722
    jc    file_read_eof         ; end of file or cluster out of range
1723
 
1724
    test  edx,edx               ; is all read?
1725
    je    file_read_OK          ; yes
1726
 
1727
    call  get_FAT               ; get next cluster
1728
    cmp   eax,[fatRESERVED]     ; end of file
1729
    jnb   file_read_eof
1730
    cmp   eax,2                 ; incorrect fat chain
1731
    jnb   file_read_new_cluster
1732
 
1733
    popad
1734
    mov   [hd1_status],0
1735
    mov   ebx,[file_size]
1736
    mov   eax,ERROR_FAT_TABLE
1737
    ret
1738
 
1739
  file_read_eof:
1740
    popad
1741
    mov   [hd1_status],0
1742
    mov   ebx,[file_size]
1743
    mov   eax,ERROR_END_OF_FILE
1744
    ret
1745
 
1746
  file_read_OK:
1747
    popad
1748
    mov   [hd1_status],0
1749
    mov   ebx,[file_size]
1750
    xor   eax,eax
1751
    ret
1752
 
1753
  file_to_read_not_found:
1754
    popad
1755
    mov   [hd1_status],0
1756
    xor   ebx,ebx
1757
    mov   eax,ERROR_FILE_NOT_FOUND
1758
    ret
1759
 
1760
 
1761
get_dir_size:
1762
;-----------------------------------------------------
1763
; input  : eax = first cluster (0=rootdir)
1764
; output : eax = directory size in bytes
1765
;-----------------------------------------------------
1766
    push  edx
1767
    xor   edx,edx               ; count of directory clusters
1768
    test  eax,eax
1769
    jnz   dir_size_next
1770
 
1771
    mov   eax,[ROOT_SECTORS]
1772
    shl   eax,9                 ; fat16 rootdir size in bytes
1773
    cmp   [fat_type],16
1774
    je    dir_size_ret
1775
    mov   eax,[ROOT_CLUSTER]
1776
 
1777
  dir_size_next:
1778
    cmp   eax,2                 ; incorrect fat chain
1779
    jb    dir_size_end
1780
    cmp   eax,[fatRESERVED]     ; end of directory
1781
    ja    dir_size_end
1782
    call  get_FAT               ; get next cluster
1783
    inc   edx
1784
    jmp   dir_size_next
1785
 
1786
  dir_size_end:
1787
    imul  eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
1788
    imul  eax,edx
1789
 
1790
  dir_size_ret:
1791
    pop   edx
1792
    ret
1793
 
1794
 
1795
file_delete:
1796
;-----------------------------------------------------
1797
; input  : eax = file/directory name
1798
;          edx = path
1799
;          edi = 1 - allow directory remove else don't remove directory
1800
; output : eax = 0 - ok
1801
;                3 - unknown FS
1802
;                5 - file not found
1803
;               10 - access denied
1804
;-----------------------------------------------------
1805
    cmp   [fat_type],0
1806
    jnz   file_del_fat_ok
1807
    mov   eax,ERROR_UNKNOWN_FS
1808
    ret
1809
 
1810
  file_del_fat_ok:
1811
    pushad
1812
 
1813
    mov   ebx,edx
1814
    call  get_cluster_of_a_path
1815
    jc    file_to_delete_not_found
1816
 
1817
    mov   ebx,PUSHAD_EAX        ; file/directory name
1818
    call  analyze_directory
1819
    jc    file_to_delete_not_found
1820
 
1821
    test  byte [ebx+11],0x10    ; is it directory?
1822
    jz    delete_notdir         ; no. it's file
1823
    cmp   edi,1                 ; allow directory remove
1824
    jnz   delete_no_access      ; no
1825
 
1826
    push  eax                   ; save directory sector
1827
    mov   eax,[ebx+20-2]        ; first cluster of file
1828
    mov   ax,[ebx+26]           ; 0 length files start cluster = 0
1829
    and   eax,[fatMASK]
1830
    xor   ebp,ebp               ; counter for directory deepnes
1831
    call  clear_directory
1832
    pop   eax
1833
    jc    delete_no_access
1834
 
1835
    push  ebx                   ; save directory pointer in buffer
1836
    mov   ebx,buffer
1837
    call  hd_read               ; read directory sector
1838
    pop   ebx
1839
 
1840
  delete_notdir:
1841
    call  delete_entry_name
1842
    mov   eax,ecx               ; first cluster of file
1843
    call  clear_cluster_chain
1844
    popad
1845
    xor   eax,eax
1846
    ret
1847
 
1848
  delete_no_access:
1849
    popad
1850
    mov   eax,ERROR_ACCESS_DENIED
1851
    ret
1852
 
1853
  file_to_delete_not_found:
1854
    popad
1855
    mov   eax,ERROR_FILE_NOT_FOUND
1856
    ret
1857
 
1858
 
1859
clear_cluster_chain:
1860
;-----------------------------------------------------
1861
; input  : eax = first cluster
1862
;-----------------------------------------------------
1863
    push  eax ecx edx
1864
    xor   ecx,ecx               ; cluster count
1865
    mov   [f_del],1             ; delete on
1866
 
1867
  clean_new_chain:
1868
    cmp   eax,[LAST_CLUSTER]    ; end of file
1869
    ja    delete_OK
1870
    cmp   eax,2                 ; unfinished fat chain or zero length file
1871
    jb    delete_OK
1872
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1873
    jz    delete_OK
1874
 
1875
    xor   edx,edx
1876
    call  set_FAT               ; clear fat entry
1877
    inc   ecx                   ; update cluster count
1878
    mov   eax,edx               ; old cluster
1879
    jmp   clean_new_chain
1880
 
1881
  delete_OK:
1882
    call  add_disk_free_space   ; add clusters to free disk space
1883
    mov   [f_del],0
1884
    pop   edx ecx eax
1885
    ret
1886
 
1887
 
1888
clear_directory:
1889
;-----------------------------------------------------
1890
; input  : eax = directory cluster
1891
;          ebp = directory deepnes
1892
; Note   : use recursive call
1893
;-----------------------------------------------------
1894
    pushad
1895
    inc   ebp
1896
    cmp   ebp,64                ; if over 63 directory deep
1897
    jnb   clear_error           ; something must be wrong
1898
 
1899
  clear_new_cluster:
1900
    cmp   eax,[LAST_CLUSTER]
1901
    ja    clear_end
1902
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1903
    jz    clear_end
1904
    mov   esi,eax               ; esi = current directory cluster
1905
    sub   eax,2
1906
    jb    clear_end
1907
    mov   ecx,[SECTORS_PER_CLUSTER]
1908
    imul  eax,ecx
1909
    add   eax,[DATA_START]
1910
 
1911
  clear_new_sector:
1912
    mov   edi,eax               ; edi = current directory sector
1913
    mov   ebx,deltree_buffer
1914
    call  hd_read
1915
    mov   edx,512/32            ; count of dir entrys per sector = 16
1916
 
1917
  clear_analyze:
1918
    mov   al,[ebx+11]           ; file attribute
1919
    and   al,0xf
1920
    cmp   al,0xf
1921
    je    clear_long_filename
1922
 
1923
    cmp   byte [ebx],'.'        ; parent or current directory
1924
    je    clear_next_entry
1925
    cmp   byte [ebx],0xe5       ; deleted
1926
    je    clear_next_entry
1927
    cmp   byte [ebx],0          ; empty
1928
    je    clear_write_last
1929
    ;je    clear_next_entry
1930
 
1931
    mov   eax,[ebx+20-2]        ; first cluster of entry
1932
    mov   ax,[ebx+26]
1933
    and   eax,[fatMASK]
1934
 
1935
    test  byte [ebx+11],0x10    ; is it directory?
1936
    jz    clear_file            ; no
1937
 
1938
    push  eax ebx
1939
    mov   eax,edi
1940
    mov   ebx,deltree_buffer    ; save buffer over recursive call
1941
    call  hd_write              ; write directory sector to disk
1942
    pop   ebx eax
1943
 
1944
    call  clear_directory       ; recursive call !!!
1945
    jc    clear_error           ; exit if error found
1946
 
1947
    push  eax ebx
1948
    mov   eax,edi
1949
    mov   ebx,deltree_buffer
1950
    call  hd_read               ; read directory sector again
1951
    pop   ebx eax
1952
 
1953
  clear_file:
1954
    call  clear_cluster_chain
1955
 
1956
  clear_long_filename:
1957
    mov   byte [ebx],0xe5
1958
 
1959
  clear_next_entry:
1960
    add   ebx,32                ; position of next dir entry
1961
    dec   edx
1962
    jnz   clear_analyze
1963
 
1964
    mov   eax,edi
1965
    mov   ebx,deltree_buffer
1966
    call  hd_write              ; write directory sector to disk
1967
 
1968
    inc   eax                   ; next sector
1969
    dec   ecx
1970
    jnz   clear_new_sector
1971
 
1972
    mov   eax,esi
1973
    call  get_FAT               ; get next cluster
1974
    jmp   clear_new_cluster     ; clear it
1975
 
1976
  clear_write_last:
1977
    mov   eax,edi
1978
    mov   ebx,deltree_buffer
1979
    call  hd_write              ; write directory sector to disk
1980
 
1981
  clear_end:
1982
    popad
1983
    clc
1984
    ret
1985
 
1986
  clear_error:
1987
    popad
1988
    stc
1989
    ret
1990
 
1991
 
1992
delete_entry_name:
1993
;-----------------------------------------------------
1994
; input  : eax = directory sector
1995
;          ebx = directory pointer in buffer
1996
;          longname_sec = 2 previous directory sectors
1997
; output : ecx = first cluster
1998
; change : eax,ebx,edx
1999
;-----------------------------------------------------
2000
    mov   byte [ebx],0xe5
2001
    mov   ecx,[ebx+20-2]        ; first cluster of file
2002
    mov   cx,[ebx+26]           ; 0 length files start cluster = 0
2003
    and   ecx,[fatMASK]
2004
 
2005
  delete_empty:
2006
    sub   ebx,32
2007
    cmp   ebx,buffer
2008
    jnb   delete_test_long
2009
 
2010
    mov   ebx,buffer
2011
    call  hd_write              ; write directory sector back
2012
    xor   eax,eax
2013
    xchg  eax,[longname_sec2]
2014
    xchg  eax,[longname_sec1]
2015
    test  eax,eax               ; is there previous directory sector?
2016
    jz    delete_name_end       ; no
2017
 
2018
    mov   ebx,buffer
2019
    call  hd_read               ; read previous sector
2020
    mov   ebx,buffer+0x1e0      ; start from last entry
2021
 
2022
  delete_test_long:
2023
    mov   dh,[ebx+11]           ; file attribute
2024
    and   dh,0xf
2025
    cmp   dh,0xf
2026
    jne   delete_write_buffer
2027
 
2028
    cmp   byte [ebx],0x40       ; end of long dir entry?
2029
    mov   byte [ebx],0xe5
2030
    jb    delete_empty
2031
 
2032
  delete_write_buffer:
2033
    mov   ebx,buffer
2034
    call  hd_write              ; write directory sector back
2035
 
2036
  delete_name_end:
2037
    ret
2038
 
2039
 
2040
rename:
2041
;-----------------------------------------------------------
2042
; input  : eax = source directory name
2043
;          edx = source path
2044
;          ebx = dest directory name
2045
;          edi = dest path
2046
; output : eax = 0 - ok
2047
;                3 - unknown FS
2048
;                5 - file not found
2049
;                8 - disk full
2050
;               10 - access denied
2051
;-----------------------------------------------------------
2052
    cmp   [fat_type],0
2053
    jnz   fat_ok_for_rename
2054
    mov   eax,ERROR_UNKNOWN_FS
2055
    ret
2056
 
2057
  fat_ok_for_rename:
2058
;    call  reserve_hd1
2059
 
2060
    pushad
2061
 
2062
    mov   ebx,edx               ; source path
2063
    call  get_cluster_of_a_path
2064
    jc    rename_entry_not_found
2065
 
2066
    mov   ebx,PUSHAD_EAX        ; source directory name
2067
    call  analyze_directory
2068
    jc    rename_entry_not_found
2069
 
2070
    mov   [sector_tmp],eax      ; save source sector
2071
    mov   [entry_pos],ebx
2072
    mov   esi,ebx
2073
    mov   edi,dir_entry
2074
    mov   ecx,32/4
2075
    cld
2076
    rep   movsd                 ; save entry
2077
 
2078
    mov   ebx,PUSHAD_EDI        ; dest path
2079
    call  get_cluster_of_a_path
2080
    jc    rename_entry_not_found
2081
 
2082
    mov   edx,eax               ; save dest directory cluster
2083
    mov   ebx,PUSHAD_EBX        ; dest directory name
2084
    push  [longname_sec1]
2085
    push  [longname_sec2]
2086
    call  analyze_directory     ; check if entry already exist
2087
    pop   [longname_sec2]
2088
    pop   [longname_sec1]
2089
    jnc   rename_entry_already_exist
2090
 
2091
    mov   eax,edx
2092
    call  analyze_directory_to_write
2093
    jc    rename_disk_full
2094
 
2095
    mov   esi,dir_entry
2096
    mov   edi,ebx
2097
    mov   ecx,32/4
2098
    cld
2099
    rep   movsd                 ; copy entry
2100
    mov   esi,PUSHAD_EBX        ; dest directory name
2101
    mov   edi,ebx
2102
    mov   ecx,11
2103
    rep   movsb                 ; copy name
2104
 
2105
    mov   ebx,buffer            ; save the directory name,length,cluster
2106
    call  hd_write
2107
 
2108
    test  byte [dir_entry+11],0x10 ; is it directory?
2109
    jz    rename_not_dir           ; no
2110
    mov   eax,[dir_entry+20-2]     ; FAT entry
2111
    mov   ax,[dir_entry+26]
2112
    and   eax,[fatMASK]
2113
    call  change_2dot_cluster
2114
 
2115
  rename_not_dir:
2116
    mov   eax,[sector_tmp]
2117
    mov   ebx,buffer
2118
    call  hd_read               ; read source directory sector
2119
 
2120
    mov   ebx,[entry_pos]
2121
    call  delete_entry_name
2122
 
2123
    popad
2124
    call  update_disk           ; write all of cache and fat to hd
2125
    mov   [hd1_status],0
2126
    xor   eax,eax
2127
    ret
2128
 
2129
  rename_entry_not_found:
2130
    popad
2131
    mov   [hd1_status],0
2132
    mov   eax,ERROR_FILE_NOT_FOUND
2133
    ret
2134
 
2135
  rename_entry_already_exist:
2136
    popad
2137
    mov   [hd1_status],0
2138
    mov   eax,ERROR_ACCESS_DENIED
2139
    ret
2140
 
2141
  rename_disk_full:
2142
    popad
2143
    mov   [hd1_status],0
2144
    mov   eax,ERROR_DISK_FULL
2145
    ret
2146
 
2147
 
2148
change_2dot_cluster:
2149
;-----------------------------------------------------------
2150
; input  : eax = directory cluster
2151
;          edx = value to save
2152
; change : eax,ebx,edx
2153
;-----------------------------------------------------------
2154
    cmp   eax,[LAST_CLUSTER]
2155
    ja    not_2dot              ; too big cluster number, something is wrong
2156
    sub   eax,2
2157
    jb    not_2dot
2158
 
2159
    imul  eax,[SECTORS_PER_CLUSTER]
2160
    add   eax,[DATA_START]
2161
    mov   ebx,buffer
2162
    call  hd_read
2163
 
2164
    cmp   dword [ebx+32],'..  '
2165
    jnz   not_2dot
2166
 
2167
    cmp   edx,[ROOT_CLUSTER]    ; is rootdir cluster?
2168
    jne   not_2dot_root
2169
    xor   edx,edx               ; yes. set it zero
2170
 
2171
  not_2dot_root:
2172
    mov   [ebx+32+26],dx        ; 16 bits low of cluster
2173
    shr   edx,16
2174
    mov   [ebx+32+20],dx        ; 16 bits high of cluster (=0 fat16)
2175
    call  hd_write
2176
 
2177
  not_2dot:
2178
    ret
2179
 
2180
 
2181
get_filesize:
2182
;-----------------------------------------------------------
2183
; input  : eax = file name
2184
;          edx = path
2185
;          edi = if 0 - read rootdir else normal dir/file size
2186
; output : eax = 0 - ok
2187
;                3 - unknown FS
2188
;                5 - file not found
2189
;          ebx = file size
2190
;-----------------------------------------------------------
2191
    cmp   [fat_type],0
2192
    jnz   get_filesize_fat_ok
2193
    xor   ebx,ebx
2194
    mov   eax,ERROR_UNKNOWN_FS
2195
    ret
2196
 
2197
  get_filesize_fat_ok:
2198
;    call  reserve_hd1
2199
 
2200
    pushad
2201
    xor   eax,eax
2202
    test  edi,edi               ; is read rootdir?
2203
    je    get_filesize_dirsize  ; yes
2204
 
2205
  get_filesize_no_root:
2206
    mov   ebx,edx
2207
    call  get_cluster_of_a_path
2208
    jc    get_filesize_not_found
2209
 
2210
    mov   ebx,PUSHAD_EAX        ; file name
2211
    call  analyze_directory
2212
    jc    get_filesize_not_found
2213
 
2214
    mov   eax,[ebx+28]          ; file size
2215
    test  byte [ebx+11],0x10    ; is it directory?
2216
    jz    get_filesize_set_size ; no
2217
 
2218
    mov   eax,[ebx+20-2]        ; FAT entry
2219
    mov   ax,[ebx+26]
2220
    and   eax,[fatMASK]
2221
 
2222
  get_filesize_dirsize:
2223
    call  get_dir_size
2224
 
2225
  get_filesize_set_size:
2226
    mov   PUSHAD_EBX,eax
2227
    popad
2228
    mov   [hd1_status],0
2229
    xor   eax,eax
2230
    ret
2231
 
2232
  get_filesize_not_found:
2233
    popad
2234
    mov   [hd1_status],0
2235
    xor   ebx,ebx
2236
    mov   eax,ERROR_FILE_NOT_FOUND
2237
    ret
2238
 
2239
 
2240
get_fileattr:
2241
;-----------------------------------------------------------
2242
; input  : eax = file name
2243
;          edx = path
2244
; output : eax = 0 - ok
2245
;                3 - unknown FS
2246
;                5 - file not found
2247
;          ebx = file attribute
2248
;-----------------------------------------------------------
2249
    cmp   [fat_type],0
2250
    jnz   get_fileattr_fat_ok
2251
    xor   ebx,ebx
2252
    mov   eax,ERROR_UNKNOWN_FS
2253
    ret
2254
 
2255
  get_fileattr_fat_ok:
2256
;    call  reserve_hd1
2257
 
2258
    pushad
2259
    mov   ebx,edx
2260
    call  get_cluster_of_a_path
2261
    jc    get_fileattr_not_found
2262
 
2263
    mov   ebx,PUSHAD_EAX        ; file name
2264
    call  analyze_directory
2265
    jc    get_fileattr_not_found
2266
 
2267
    movzx eax,byte [ebx+11]     ; file attribute
2268
    mov   PUSHAD_EBX,eax
2269
    popad
2270
    mov   [hd1_status],0
2271
    xor   eax,eax
2272
    ret
2273
 
2274
  get_fileattr_not_found:
2275
    popad
2276
    mov   [hd1_status],0
2277
    xor   ebx,ebx
2278
    mov   eax,ERROR_FILE_NOT_FOUND
2279
    ret
2280
 
2281
 
2282
get_filedate:
2283
;-----------------------------------------------------------
2284
; input  : eax = file name
2285
;          edx = path
2286
; output : eax = 0 - ok
2287
;                3 - unknown FS
2288
;                5 - file not found
2289
;          ebx = file date/time
2290
;                bits 31..25 = year-1980
2291
;                bits 24..21 = month
2292
;                bits 20..16 = day
2293
;                bits 15..11 = hour
2294
;                bits 10..5  = minute
2295
;                bits 4..0   = second/2
2296
;-----------------------------------------------------------
2297
    cmp   [fat_type],0
2298
    jnz   get_filedate_fat_ok
2299
    xor   ebx,ebx
2300
    mov   eax,ERROR_UNKNOWN_FS
2301
    ret
2302
 
2303
  get_filedate_fat_ok:
2304
;    call  reserve_hd1
2305
 
2306
    pushad
2307
    mov   ebx,edx
2308
    call  get_cluster_of_a_path
2309
    jc    get_filedate_not_found
2310
 
2311
    mov   ebx,PUSHAD_EAX        ; file name
2312
    call  analyze_directory
2313
    jc    get_filedate_not_found
2314
 
2315
    mov   eax,[ebx+22]          ; file date/time
2316
    mov   PUSHAD_EBX,eax
2317
    popad
2318
    mov   [hd1_status],0
2319
    xor   eax,eax
2320
    ret
2321
 
2322
  get_filedate_not_found:
2323
    popad
2324
    mov   [hd1_status],0
2325
    xor   ebx,ebx
2326
    mov   eax,ERROR_FILE_NOT_FOUND
2327
    ret
2328
 
2329
 
2330
get_hd_info:
2331
;-----------------------------------------------------------
2332
; output : eax = 0 - ok
2333
;                3 - unknown FS
2334
;          edx = cluster size in bytes
2335
;          ebx = total clusters on disk
2336
;          ecx = free clusters on disk
2337
;-----------------------------------------------------------
2338
    cmp   [fat_type],0
2339
    jnz   info_fat_ok
2340
    xor   edx,edx
2341
    xor   ebx,ebx
2342
    xor   ecx,ecx
2343
    mov   eax,ERROR_UNKNOWN_FS
2344
    ret
2345
 
2346
  info_fat_ok:
2347
;    call  reserve_hd1
2348
 
2349
    xor   ecx,ecx               ; count of free clusters
2350
    mov   eax,2
2351
    mov   ebx,[LAST_CLUSTER]
2352
 
2353
  info_cluster:
2354
    push  eax
2355
    call  get_FAT               ; get cluster info
2356
    test  eax,eax               ; is it free?
2357
    jnz   info_used             ; no
2358
    inc   ecx
2359
 
2360
  info_used:
2361
    pop   eax
2362
    inc   eax
2363
    cmp   eax,ebx               ; is above last cluster?
2364
    jbe   info_cluster          ; no. test next cluster
2365
 
2366
    dec   ebx                   ; cluster count
2367
    imul  edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
2368
    mov   [hd1_status],0
2369
    xor   eax,eax
2370
    ret
2371
 
2372
 
2373
update_disk:
2374
;-----------------------------------------------------------
2375
; write changed fat and cache to disk
2376
;-----------------------------------------------------------
2377
    cmp   [fat_change],0        ; is fat changed?
2378
    je    upd_no_change
2379
 
2380
    call  write_fat_sector
2381
 
2382
  upd_no_change:
2383
 
2384
    call  write_cache
2385
    ret
2386
 
2387
 
2388
;**************************************************************************
2389
;
2390
;   0x600008  - first entry in cache list
2391
;
2392
;            +0   - lba sector
2393
;            +4   - state of cache sector
2394
;                   0 = empty
2395
;                   1 = used for read  ( same as in hd )
2396
;                   2 = used for write ( differs from hd )
2397
;
2398
;      +65536 - cache entries
2399
;
2400
;**************************************************************************
2401
 
2402
 
2403
hd_read:
2404
;-----------------------------------------------------------
2405
; input  : eax = block to read
2406
;          ebx = destination
2407
;-----------------------------------------------------------
2408
    push  ecx esi edi           ; scan cache
2409
 
2410
    mov   ecx,cache_max         ; entries in cache
2411
    mov   esi,0x600000+8
2412
    mov   edi,1
2413
 
2414
  hdreadcache:
2415
 
2416
    cmp   dword [esi+4],0       ; empty
2417
    je    nohdcache
2418
 
2419
    cmp   [esi],eax             ; correct sector
2420
    je    yeshdcache
2421
 
2422
  nohdcache:
2423
 
2424
    add   esi,8
2425
    inc   edi
2426
    dec   ecx
2427
    jnz   hdreadcache
2428
 
2429
    call  find_empty_slot       ; ret in edi
2430
 
2431
    call  wait_for_hd_idle
2432
    push  eax edx
2433
 
2434
    cli
2435
    xor   eax,eax
2436
    mov   edx,[hdbase]
2437
    inc   edx
2438
    out   dx,al   ; ATAFeatures ðåãèñòð "îñîáåííîñòåé"
2439
    inc   edx
2440
    inc   eax
2441
    out   dx,al   ; ATASectorCount ñ÷åò÷èê ñåêòîðîâ
2442
    inc   edx
2443
    mov   eax,[esp+4]
2444
    out   dx,al   ; ATASectorNumber ðåãèñòð íîìåðà ñåêòîðà
2445
    shr   eax,8
2446
    inc   edx
2447
    out   dx,al   ; ATACylinder íîìåð öèëèíäðà (ìëàäøèé áàéò)
2448
    shr   eax,8
2449
    inc   edx
2450
    out   dx,al   ; íîìåð öèëèíäðà (ñòàðøèé áàéò)
2451
    shr   eax,8
2452
    inc   edx
2453
    and   al,1+2+4+8
2454
    add   al,byte [hdid]
2455
    add   al,128+64+32
2456
    out   dx,al   ; íîìåð ãîëîâêè/íîìåð äèñêà
2457
    inc   edx
2458
    mov   al,20h
2459
    out   dx,al   ; ATACommand ðåãèñòð êîìàíä
2460
    sti
2461
 
2462
    call  wait_for_sector_buffer
2463
 
2464
    cmp   [hd_error],0
2465
    jne   hd_read_error
2466
 
2467
    cli
2468
    push  edi
2469
    shl   edi,9
2470
    add   edi,0x600000+65536
2471
    mov   ecx,256
2472
    mov   edx,[hdbase]
2473
    cld
2474
    rep   insw
2475
    pop   edi
2476
    sti
2477
 
2478
    pop   edx eax
2479
 blok_read_2:
2480
    lea   esi,[edi*8+0x600000]
2481
    mov   [esi],eax             ; sector number
2482
    mov   dword [esi+4],1       ; hd read - mark as same as in hd
2483
 
2484
  yeshdcache:
2485
 
2486
    mov   esi,edi
2487
    shl   esi,9
2488
    add   esi,0x600000+65536
2489
    mov   edi,ebx
2490
    mov   ecx,512/4
2491
    cld
2492
    rep   movsd                 ; move data
2493
; blok_read_2:
2494
    pop   edi esi ecx
2495
    ret
2496
 
2497
 
2498
hd_write:
2499
;-----------------------------------------------------------
2500
; input  : eax = block
2501
;          ebx = pointer to memory
2502
;-----------------------------------------------------------
2503
    push  ecx esi edi
2504
 
2505
    ; check if the cache already has the sector and overwrite it
2506
 
2507
    mov   ecx,cache_max
2508
    mov   esi,0x600000+8
2509
    mov   edi,1
2510
 
2511
  hdwritecache:
2512
 
2513
    cmp   dword [esi+4],0       ; if cache slot is empty
2514
    je    not_in_cache_write
2515
 
2516
    cmp   [esi],eax             ; if the slot has the sector
2517
    je    yes_in_cache_write
2518
 
2519
  not_in_cache_write:
2520
 
2521
    add   esi,8
2522
    inc   edi
2523
    dec   ecx
2524
    jnz   hdwritecache
2525
 
2526
    ; sector not found in cache
2527
    ; write the block to a new location
2528
 
2529
    call  find_empty_slot       ; ret in edi
2530
 
2531
    lea   esi,[edi*8+0x600000]
2532
    mov   [esi],eax             ; sector number
2533
 
2534
  yes_in_cache_write:
2535
 
2536
    mov   dword [esi+4],2       ; write - differs from hd
2537
 
2538
    shl   edi,9
2539
    add   edi,0x600000+65536
2540
    mov   esi,ebx
2541
    mov   ecx,512/4
2542
    cld
2543
    rep   movsd                 ; move data
2544
 
2545
    pop   edi esi ecx
2546
    ret
2547
 
2548
 
2549
write_cache:
2550
;-----------------------------------------------------------
2551
; write all changed sectors to disk
2552
;-----------------------------------------------------------
2553
    push  eax ecx edx esi edi
2554
 
2555
    ; write difference ( 2 ) from cache to hd
2556
 
2557
    mov   ecx,cache_max
2558
    mov   esi,0x600000+8
2559
    mov   edi,1
2560
 
2561
  write_cache_more:
2562
 
2563
    cmp   dword [esi+4],2       ; if cache slot is not different
2564
    jne   does_not_need_writing
2565
 
2566
    mov   dword [esi+4],1       ; same as in hd
2567
    mov   eax,[esi]             ; eax = sector to write
2568
 
2569
    cmp   eax,[PARTITION_START]
2570
    jb    danger
2571
    cmp   eax,[PARTITION_END]
2572
    ja    danger
2573
 
2574
    call  wait_for_hd_idle
2575
 
2576
    cli
2577
    xor   eax,eax
2578
    mov   edx,[hdbase]
2579
    inc   edx
2580
    out   dx,al
2581
    inc   edx
2582
    inc   eax
2583
    out   dx,al
2584
    inc   edx
2585
    mov   eax,[esi]             ; eax = sector to write
2586
    out   dx,al
2587
    shr   eax,8
2588
    inc   edx
2589
    out   dx,al
2590
    shr   eax,8
2591
    inc   edx
2592
    out   dx,al
2593
    shr   eax,8
2594
    inc   edx
2595
    and   al,1+2+4+8
2596
    add   al,byte [hdid]
2597
    add   al,128+64+32
2598
    out   dx,al
2599
    inc   edx
2600
    mov   al,30h
2601
    out   dx,al
2602
    sti
2603
 
2604
    call  wait_for_sector_buffer
2605
 
2606
    cmp   [hd_error],0
2607
    jne   hd_write_error
2608
 
2609
    push  ecx esi
2610
 
2611
    cli
2612
    mov   esi,edi
2613
    shl   esi,9
2614
    add   esi,0x600000+65536    ; esi = from memory position
2615
    mov   ecx,256
2616
    mov   edx,[hdbase]
2617
    cld
2618
    rep   outsw
2619
    sti
2620
 
2621
    pop   esi ecx
2622
 
2623
  danger:
2624
  does_not_need_writing:
2625
 
2626
    add   esi,8
2627
    inc   edi
2628
    dec   ecx
2629
    jnz   write_cache_more
2630
 
2631
    pop   edi esi edx ecx eax
2632
    ret
2633
 
2634
 
2635
find_empty_slot:
2636
;-----------------------------------------------------------
2637
; find empty or read slot, flush cache if next 10% is used by write
2638
; output : edi = cache slot
2639
;-----------------------------------------------------------
2640
    push  ecx esi
2641
 
2642
  search_again:
2643
 
2644
    mov   ecx,cache_max*10/100
2645
    mov   edi,[cache_search_start]
2646
 
2647
  search_for_empty:
2648
 
2649
    inc   edi
2650
    cmp   edi,cache_max
2651
    jbe   inside_cache
2652
    mov   edi,1
2653
 
2654
  inside_cache:
2655
 
2656
    cmp   dword [edi*8+0x600000+4],2    ; get cache slot info
2657
    jb    found_slot                    ; it's empty or read
2658
    dec   ecx
2659
    jnz   search_for_empty
2660
 
2661
    call  write_cache                   ; no empty slots found, write all
2662
    jmp   search_again                  ; and start again
2663
 
2664
  found_slot:
2665
 
2666
    mov   [cache_search_start],edi
2667
 
2668
    pop   esi ecx
2669
    ret
2670
 
2671
 
2672
save_hd_wait_timeout:
2673
 
2674
    push  eax
2675
    mov   eax,[timer_ticks];[0xfdf0]
2676
    add   eax,300               ; 3 sec timeout
2677
    mov   [hd_wait_timeout],eax
2678
    pop   eax
2679
    ret
2680
 
2681
 
2682
check_hd_wait_timeout:
2683
 
2684
    push  eax
2685
    mov   eax,[hd_wait_timeout]
2686
    cmp   [timer_ticks], eax ;[0xfdf0],eax
2687
    jg    hd_timeout_error
2688
    pop   eax
2689
    ret
2690
 
2691
iglobal
2692
  hd_timeout_str   db 'K : FS - HD timeout',13,10,0
2693
  hd_read_str      db 'K : FS - HD read error',13,10,0
2694
  hd_write_str     db 'K : FS - HD write error',13,10,0
2695
endg
2696
 
2697
hd_timeout_error:
2698
 
2699
    call  clear_hd_cache
2700
    call  clear_application_table_status
2701
    mov   esi,hd_timeout_str
2702
    call  sys_msg_board_str
2703
    jmp   $
2704
 
2705
 
2706
hd_read_error:
2707
 
2708
    call  clear_hd_cache
2709
    call  clear_application_table_status
2710
    mov   esi,hd_read_str
2711
    call  sys_msg_board_str
2712
    jmp   $
2713
 
2714
hd_write_error:
2715
 
2716
    call  clear_hd_cache
2717
    call  clear_application_table_status
2718
    mov   esi,hd_write_str
2719
    call  sys_msg_board_str
2720
    jmp   $
2721
 
2722
 
2723
 
2724
 
2725
wait_for_hd_idle:
2726
 
2727
    push  eax edx
2728
 
2729
    call  save_hd_wait_timeout
2730
 
2731
    mov   edx,[hdbase]
2732
    add   edx,0x7
2733
 
2734
  wfhil1:
2735
 
2736
    call  check_hd_wait_timeout
2737
 
2738
    in    al,dx
2739
    test  al,128
2740
    jnz   wfhil1
2741
 
2742
    pop   edx eax
2743
    ret
2744
 
2745
 
2746
wait_for_sector_buffer:
2747
 
2748
    push  eax edx
2749
 
2750
    mov   edx,[hdbase]
2751
    add   edx,0x7
2752
 
2753
    call  save_hd_wait_timeout
2754
 
2755
  hdwait_sbuf:                  ; wait for sector buffer to be ready
2756
 
2757
    call  check_hd_wait_timeout
2758
 
2759
    in    al,dx
2760
    test  al,8
2761
    jz    hdwait_sbuf
2762
 
2763
    mov   [hd_error],0
2764
 
2765
    cmp   [hd_setup],1          ; do not mark error for setup request
2766
    je    buf_wait_ok
2767
 
2768
    test  al,1                  ; previous command ended up with an error
2769
    jz    buf_wait_ok
2770
    mov   [hd_error],1
2771
 
2772
  buf_wait_ok:
2773
 
2774
    pop   edx eax
2775
    ret
2776
 
2777
 
2778
 
2779
read_hd_file:
2780
;-----------------------------------------------------------------
2781
;
2782
; Converting old reading function for hd-application start.
2783
;
2784
; IN:
2785
;
2786
; eax - pointer to file (0 = read only first sector of drive: eg 'label')
2787
; ebx - file lenght
2788
; ecx - start 512 byte block number
2789
; edx - number of blocks to read
2790
; esi - pointer to return/work area (atleast 20 000 bytes)
2791
;
2792
; For new read function
2793
;
2794
; EAX   (PAR0)      pointer to file-name
2795
; ECX   (PAR1)      pointer to buffer
2796
; EBX   (PAR2)   vt file blocks to read
2797
; EDX   (PAR3)      pointer to path
2798
; ESI            vt first 512 block to read
2799
; EDI               if 0 - return root
2800
;--------------------------------------------------------------------------
2801
 
2802
    push  ecx esi edi
2803
    mov   esi,eax
2804
    mov   edi,startpath
2805
    mov   ecx,250
2806
    cld
2807
    rep   movsb
2808
    pop   edi esi ecx
2809
 
2810
    mov   eax,startpath
2811
    mov   [eax+ebx-12],byte 0
2812
 
2813
    push  eax ebx ecx edx esi
2814
 
2815
    pop   ecx ; pointer to buffer
2816
    add   ecx,1024
2817
    pop   ebx ; number of blocks to read
2818
    pop   esi ; first block to read
2819
    dec   esi
2820
    pop   eax ; file length
2821
    pop   edx ; pointer to path
2822
 
2823
    mov   edi,12
2824
    lea   eax,[eax+edx-12+1]
2825
    call  file_read
2826
 
2827
    ret
2828