Subversion Repositories Kolibri OS

Rev

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