Subversion Repositories Kolibri OS

Rev

Rev 86 | 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                                   ;;
86 diamond 10
;;  15.06.2006 LFN get/set file/folder info - diamond              ;;
83 diamond 11
;;  27.05.2006 LFN create/rewrite file - diamond                   ;;
75 diamond 12
;;  04.05.2006 LFN read folder - diamond                           ;;
74 mario79 13
;;  29.04.2006 Elimination of hangup after the                     ;;
14
;;             expiration hd_wait_timeout -  Mario79               ;;
75 diamond 15
;;  23.04.2006 LFN read file - diamond                             ;;
65 mario79 16
;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
17
;;             to MBR, see file part_set.inc - Mario79             ;;
1 ha 18
;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
19
;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
20
;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
21
;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
22
;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
23
;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
24
;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
25
;;  08.11.2004 rename - ATV                                        ;;
26
;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
27
;;  20.10.2004 Makedir/Removedir - ATV                             ;;
28
;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
29
;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
30
;;  24.5.2004  Write back buffer for File_write -VT                ;;
31
;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
32
;;  30.3.2004  Error parameters at function return - VT            ;;
33
;;  01.5.2002  Bugfix in device write - VT                         ;;
34
;;  20.5.2002  Hd status check - VT                                ;;
35
;;  29.6.2002  Improved fat32 verification - VT                    ;;
36
;;                                                                 ;;
37
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
38
 
39
cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
40
 
52 mikedld 41
ERROR_SUCCESS        = 0
42
ERROR_DISK_BASE      = 1
43
ERROR_UNSUPPORTED_FS = 2
44
ERROR_UNKNOWN_FS     = 3
45
ERROR_PARTITION      = 4
46
ERROR_FILE_NOT_FOUND = 5
47
ERROR_END_OF_FILE    = 6
48
ERROR_MEMORY_POINTER = 7
49
ERROR_DISK_FULL      = 8
50
ERROR_FAT_TABLE      = 9
51
ERROR_ACCESS_DENIED  = 10
1 ha 52
 
53
PUSHAD_EAX equ [esp+28]
54
PUSHAD_ECX equ [esp+24]
55
PUSHAD_EDX equ [esp+20]
56
PUSHAD_EBX equ [esp+16]
57
PUSHAD_EBP equ [esp+8]
58
PUSHAD_ESI equ [esp+4]
59
PUSHAD_EDI equ [esp+0]
60
 
61
cluster              dd 0       ; used by file_write,makedir,append
62
partition_count      dd 0       ; partitions found by set_FAT32_variables
63
longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
64
longname_sec2        dd 0       ; directory sectors for delete long filename
65
 
66
hd_error             dd 0       ; set by wait_for_sector_buffer
67
hd_setup             dd 0
68
hd_wait_timeout      dd 0
69
 
70
cluster_tmp          dd 0       ; used by analyze_directory
71
                                ; and analyze_directory_to_write
72
 
73
file_size            dd 0       ; used by file_read
74
 
75
sector_tmp           dd 0       ; used by rename,append,file_write
76
entry_pos            dd 0       ; used by rename,append,file_write
77
 
78
old_filesize         dd 0       ; used by append
79
new_filepos          dd 0       ; used by append
80
bytes2write          dd 0       ; used by append
81
 
82
cache_search_start   dd 0       ; used by find_empty_slot
83
 
84
fat_in_cache         dd -1
85
fat_cache:           times 512 db 0
86
 
87
uglobal
88
 Sector512:                      ; label for dev_hdcd.inc
89
  buffer:              times 512 db 0
90
  deltree_buffer:      times 512 db 0
91
endg
92
 
93
iglobal
94
  NewDirEntry1         db ".          ",0x10
95
                     times 20 db 0
96
  NewDirEntry2         db "..         ",0x10
97
                     times 20 db 0
98
endg
99
 
100
uglobal
101
  dir_entry:           times 32 db 0
102
 
103
  startpath:           times 255 db 0
104
 
105
  fat16_root           db 0       ; flag for fat16 rootdir
106
  f_del                db 0       ; 1=overwrite fat entry
107
  fat_change           db 0       ; 1=fat has changed
108
 
109
endg
110
 
111
reserve_hd1:
112
 
113
    cli
114
    cmp   [hd1_status],0
115
    je    reserve_ok1
116
 
117
    sti
118
    call  change_task
119
    jmp   reserve_hd1
120
 
121
  reserve_ok1:
122
 
123
    push  eax
124
    mov   eax,[0x3000]
125
    shl   eax,5
126
    mov   eax,[eax+0x3000+4]
127
    mov   [hd1_status],eax
128
    pop   eax
129
    sti
130
    ret
131
 
132
 
133
clear_hd_cache:
134
 
135
    push  eax ecx edi
136
    mov   edi,0x600000
137
    mov   ecx,16384
138
    xor   eax,eax
139
    cld
140
    rep   stosd                 ; clear hd cache with 0
141
    mov   [cache_search_start],eax
142
    mov   [fat_in_cache],-1
143
    mov   [fat_change],0
144
    pop   edi ecx eax
145
    ret
146
 
147
problem_partition db 0  ; used for partitions search
148
 
65 mario79 149
include  'part_set.inc'
1 ha 150
 
151
set_FAT:
152
;--------------------------------
153
; input  : EAX = cluster
154
;          EDX = value to save
155
; output : EDX = old value
156
;--------------------------------
157
    push  eax ebx esi
158
 
159
    cmp   eax,2
160
    jb    sfc_error
161
    cmp   eax,[LAST_CLUSTER]
162
    ja    sfc_error
163
    cmp   [fat_type],16
164
    je    sfc_1
165
    add   eax,eax
166
  sfc_1:
167
    add   eax,eax
168
    mov   esi,511
169
    and   esi,eax               ; esi = position in fat sector
170
    shr   eax,9                 ; eax = fat sector
171
    add   eax,[FAT_START]
172
    mov   ebx,fat_cache
173
 
174
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
175
    je    sfc_in_cache          ; yes
176
 
177
    cmp   [fat_change],0        ; is fat changed?
178
    je    sfc_no_change         ; no
179
    call  write_fat_sector      ; yes. write it into disk
74 mario79 180
    cmp   [hd_error],0
181
    jne   sfc_error
1 ha 182
 
183
  sfc_no_change:
184
    mov   [fat_in_cache],eax    ; save fat sector
185
    call  hd_read
74 mario79 186
    cmp  [hd_error],0
187
    jne  sfc_error
188
 
1 ha 189
 
190
  sfc_in_cache:
191
    cmp   [fat_type],16
192
    jne   sfc_test32
193
 
194
    cmp   [f_del],1             ; overwrite previous value?
195
    je    sfc_set16             ; yes
196
    cmp   word [ebx+esi],0      ; is cluster free?
197
    je    sfc_set16             ; yes
198
    mov   dword [8*0x100000],0xffffff
199
    mov   edx,[ebx+esi]         ; get old value
200
    jmp   sfc_nonzero
201
 
202
  sfc_set16:
203
    xchg  [ebx+esi],dx          ; save new value and get old value
204
    jmp   sfc_write
205
 
206
  sfc_test32:
207
    mov   eax,[fatMASK]
208
    cmp   [f_del],1             ; overwrite previous value?
209
    je    sfc_set32             ; yes
210
    test  eax,[ebx+esi]         ; is cluster free?
211
    je    sfc_set32             ; yes
212
    mov   dword [8*0x100000],0xffffff
213
    mov   edx,[ebx+esi]         ; get old value
214
    jmp   sfc_nonzero
215
 
216
  sfc_set32:
217
    and   edx,eax
218
    xor   eax,-1                ; mask for high bits
219
    and   eax,[ebx+esi]         ; get high 4 bits
220
    or    eax,edx
221
    mov   edx,[ebx+esi]         ; get old value
222
    mov   [ebx+esi],eax         ; save new value
223
 
224
  sfc_write:
225
    mov   [fat_change],1        ; fat has changed
226
 
227
  sfc_nonzero:
228
    and   edx,[fatMASK]
229
 
230
  sfc_error:
231
    pop   esi ebx eax
232
    ret
233
 
234
 
235
get_FAT:
236
;--------------------------------
237
; input  : EAX = cluster
238
; output : EAX = next cluster
239
;--------------------------------
240
    push  ebx esi
241
 
242
    cmp   [fat_type],16
243
    je    gfc_1
244
    add   eax,eax
245
  gfc_1:
246
    add   eax,eax
247
    mov   esi,511
248
    and   esi,eax               ; esi = position in fat sector
249
    shr   eax,9                 ; eax = fat sector
250
    add   eax,[FAT_START]
251
    mov   ebx,fat_cache
252
 
253
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
254
    je    gfc_in_cache
255
 
256
    cmp   [fat_change],0        ; is fat changed?
257
    je    gfc_no_change         ; no
258
    call  write_fat_sector      ; yes. write it into disk
74 mario79 259
    cmp  [hd_error],0
260
    jne  hd_error_01
1 ha 261
 
262
  gfc_no_change:
263
    mov   [fat_in_cache],eax
264
    call  hd_read
74 mario79 265
    cmp  [hd_error],0
266
    jne  hd_error_01
1 ha 267
 
268
  gfc_in_cache:
269
    mov   eax,[ebx+esi]
270
    and   eax,[fatMASK]
74 mario79 271
 hd_error_01:
1 ha 272
    pop   esi ebx
273
    ret
274
 
275
 
276
get_free_FAT:
277
;-----------------------------------------------------------
278
; input  : EAX = # cluster for start the searching
279
; output : if CARRY=0 EAX = # first cluster found free
280
;          if CARRY=1 disk full
281
; Note   : for more speed need to use fat_cache directly
282
;-----------------------------------------------------------
283
    push  ecx
284
    mov   ecx,[LAST_CLUSTER]    ; counter for full disk
285
    sub   ecx,2
286
 
287
  gff_test:
288
    cmp   eax,[LAST_CLUSTER]    ; if above last cluster start at cluster 2
289
    jbe   gff_in_range
290
    mov   eax,2
291
 
292
  gff_in_range:
293
    push  eax
294
    call  get_FAT               ; get cluster state
74 mario79 295
    cmp   [hd_error],0
296
    jne   gff_not_found_1
297
 
1 ha 298
    test  eax,eax               ; is it free?
299
    pop   eax
300
    je    gff_found             ; yes
301
    inc   eax                   ; next cluster
302
    dec   ecx                   ; is all checked?
303
    jns   gff_test              ; no
304
 
74 mario79 305
  gff_not_found_1:
306
    add   esp,4
1 ha 307
  gff_not_found:
308
    pop   ecx                   ; yes. disk is full
309
    stc
310
    ret
311
 
312
  gff_found:
313
    pop   ecx
314
    clc
315
    ret
316
 
317
 
318
write_fat_sector:
319
;-----------------------------------------------------------
320
; write changed fat to disk
321
;-----------------------------------------------------------
322
    push  eax ebx ecx
323
 
324
    mov   [fat_change],0
325
    mov   eax,[fat_in_cache]
326
    cmp   eax,-1
327
    jz    write_fat_not_used
328
    mov   ebx,fat_cache
329
    mov   ecx,[NUMBER_OF_FATS]
330
 
331
  write_next_fat:
332
    call  hd_write
74 mario79 333
    cmp   [hd_error],0
334
    jne   write_fat_not_used
335
 
1 ha 336
    add   eax,[SECTORS_PER_FAT]
337
    dec   ecx
338
    jnz   write_next_fat
339
 
340
  write_fat_not_used:
341
    pop   ecx ebx eax
342
    ret
343
 
344
 
345
analyze_directory:
346
;-----------------------------------------------------------
347
; input  : EAX = first cluster of the directory
348
;          EBX = pointer to filename
349
; output : IF CARRY=0 EAX = sector where th file is found
350
;                     EBX = pointer in buffer
351
;                     [buffer .. buffer+511]
352
;                     ECX,EDX,ESI,EDI not changed
353
;          IF CARRY=1 filename not found
354
; Note   : if cluster=0 it's changed to read rootdir
355
;          save 2 previous directory sectors in longname_sec
356
;-----------------------------------------------------------
357
    push  ecx edx esi edi ebx   ; ebx = [esp+0]
358
    mov   [longname_sec1],0
359
    mov   [longname_sec2],0
360
 
361
  adr_new_cluster:
362
    mov   [cluster_tmp],eax
363
    mov   [fat16_root],0
364
    cmp   eax,[LAST_CLUSTER]
365
    ja    adr_not_found         ; too big cluster number, something is wrong
366
    cmp   eax,2
367
    jnb   adr_data_cluster
368
 
369
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
370
    cmp   [fat_type],16
371
    jne   adr_data_cluster
372
    mov   eax,[ROOT_START]
373
    mov   edx,[ROOT_SECTORS]
374
    mov   [fat16_root],1        ; flag for fat16 rootdir
375
    jmp   adr_new_sector
376
 
377
  adr_data_cluster:
378
    sub   eax,2
379
    mov   edx,[SECTORS_PER_CLUSTER]
380
    imul  eax,edx
381
    add   eax,[DATA_START]
382
 
383
  adr_new_sector:
384
    mov   ebx,buffer
385
    call  hd_read
74 mario79 386
    cmp  [hd_error],0
387
    jne  adr_not_found
388
 
1 ha 389
    mov   ecx,512/32            ; count of dir entrys per sector = 16
390
 
391
  adr_analyze:
392
    mov   edi,[ebx+11]          ; file attribute
393
    and   edi,0xf
394
    cmp   edi,0xf
395
    je    adr_long_filename
396
    test  edi,0x8               ; skip over volume label
397
    jne   adr_long_filename     ; Note: label can be same name as file/dir
398
 
399
    mov   esi,[esp+0]           ; filename need to be uppercase
400
    mov   edi,ebx
401
    push  ecx
402
    mov   ecx,11
403
    cld
404
    rep   cmpsb                 ; compare 8+3 filename
405
    pop   ecx
406
    je    adr_found
407
 
408
  adr_long_filename:
409
    add   ebx,32                ; position of next dir entry
410
    dec   ecx
411
    jnz   adr_analyze
412
 
413
    mov   ecx,[longname_sec1]   ; save 2 previous directory sectors
414
    mov   [longname_sec1],eax   ; for delete long filename
415
    mov   [longname_sec2],ecx
416
    inc   eax                   ; next sector
417
    dec   edx
418
    jne   adr_new_sector
419
    cmp   [fat16_root],1        ; end of fat16 rootdir
420
    je    adr_not_found
421
 
422
  adr_next_cluster:
423
    mov   eax,[cluster_tmp]
424
    call  get_FAT               ; get next cluster
74 mario79 425
    cmp  [hd_error],0
426
    jne  adr_not_found
427
 
1 ha 428
    cmp   eax,2                 ; incorrect fat chain?
429
    jb    adr_not_found         ; yes
430
    cmp   eax,[fatRESERVED]     ; is it end of directory?
431
    jb    adr_new_cluster       ; no. analyse it
432
 
433
  adr_not_found:
434
    pop   edi edi esi edx ecx   ; first edi will remove ebx
435
    stc                         ; file not found
436
    ret
437
 
438
  adr_found:
439
    pop   edi edi esi edx ecx   ; first edi will remove ebx
440
    clc                         ; file found
441
    ret
442
 
443
 
444
analyze_directory_to_write:
445
;-----------------------------------------------------------
446
; input  : EAX = first cluster of the directory
447
; output : IF CARRY=0 EAX = sector where the empty pos is found
448
;                     EBX = pointer in buffer
449
;                     [buffer .. buffer+511]
450
;                     ECX,EDX,ESI,EDI not changed
451
;          IF CARRY=1 disk full or fat corrupted
452
; Note   : if cluster=0 it's changed to read rootdir
453
;-----------------------------------------------------------
454
    push  ecx edx edi
455
 
456
  adw_new_cluster:
457
    mov   [cluster_tmp],eax
458
    mov   [fat16_root],0
459
    cmp   eax,[LAST_CLUSTER]
460
    ja    adw_not_found         ; too big cluster number, something is wrong
461
    cmp   eax,2
462
    jnb   adw_data_cluster
463
 
464
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
465
    cmp   [fat_type],16
466
    jne   adw_data_cluster
467
    mov   eax,[ROOT_START]
468
    mov   edx,[ROOT_SECTORS]
469
    mov   [fat16_root],1        ; flag for fat16 rootdir
470
    jmp   adw_new_sector
471
 
472
  adw_data_cluster:
473
    sub   eax,2
474
    mov   edx,[SECTORS_PER_CLUSTER]
475
    imul  eax,edx
476
    add   eax,[DATA_START]
477
 
478
  adw_new_sector:
479
    mov   ebx,buffer
480
    call  hd_read
74 mario79 481
    cmp  [hd_error],0
482
    jne  adw_not_found
483
 
1 ha 484
    mov   ecx,512/32            ; count of dir entrys per sector = 16
485
 
486
  adw_analyze:
487
    cmp   byte [ebx],0x00       ; is free entry?
488
    je    adw_found             ; yes
489
    cmp   byte [ebx],0xe5       ; is deleted entry?
490
    je    adw_found             ; yes
491
    add   ebx,32                ; position of next dir entry
492
    dec   ecx
493
    jnz   adw_analyze
494
 
495
    inc   eax                   ; next sector
496
    dec   edx
497
    jne   adw_new_sector
498
    cmp   [fat16_root],1        ; end of fat16 rootdir
499
    je    adw_not_found
500
 
501
    mov   eax,[cluster_tmp]
502
    call  get_FAT               ; get next cluster
74 mario79 503
    cmp   [hd_error],0
504
    jne   adw_not_found
505
 
1 ha 506
    cmp   eax,2                 ; incorrect fat chain?
507
    jb    adw_not_found         ; yes
508
    cmp   eax,[fatRESERVED]     ; is it end of directory?
509
    jb    adw_new_cluster       ; no. analyse it
510
 
511
    mov   eax,2                 ; this block of code add a new cluster
512
    call  get_free_FAT          ; for the directory because the directory
513
    jc    adw_not_found         ; is full
514
 
515
    mov   edx,[fatEND]          ; new end for directory
516
    call  set_FAT
74 mario79 517
    cmp  [hd_error],0
518
    jne  adw_not_found
1 ha 519
 
520
    push  eax                   ; save new cluster
521
    mov   edx,eax
522
    mov   eax,[cluster_tmp]     ; change last cluster to point new cluster
523
    mov   [f_del],1
524
    call  set_FAT
74 mario79 525
    cmp  [hd_error],0
526
    jne  adw_not_found_1
527
 
1 ha 528
    mov   [f_del],0
529
 
530
    mov   ecx,-1                ; remove 1 cluster from free disk space
531
    call  add_disk_free_space
74 mario79 532
    cmp  [hd_error],0
533
    jne    adw_not_found_1
1 ha 534
 
535
    mov   ecx,512/4
536
    xor   eax,eax
537
    mov   edi,buffer
538
    cld
539
    rep   stosd                 ; clear new directory cluster
540
    pop   eax
541
 
542
    sub   eax,2
543
    mov   ecx,[SECTORS_PER_CLUSTER]
544
    imul  eax,ecx
545
    add   eax,[DATA_START]
546
    mov   ebx,buffer
547
    push  eax                   ; save sector number
548
 
549
  adw_set_empty_directory:
550
    call  hd_write
74 mario79 551
    cmp   [hd_error],0
552
    jne   adw_not_found_1
553
 
1 ha 554
    inc   eax                   ; next sector
555
    dec   ecx
556
    jnz   adw_set_empty_directory
557
 
558
    pop   eax
559
 
560
  adw_found:
561
    pop   edi edx ecx
562
    clc                         ; free space found
563
    ret
74 mario79 564
  adw_not_found_1:
565
    add  esp,4
1 ha 566
  adw_not_found:
567
    pop   edi edx ecx
568
    stc                         ; free space not found
569
    ret
570
 
571
 
572
get_data_cluster:
573
;-----------------------------------------------------------
574
; input  : EAX = cluster
575
;          EBX = pointer to buffer
576
;          EDX = # blocks to read in buffer
577
;          ESI = # blocks to skip over
578
; output : if CARRY=0 ok EBX/EDX/ESI updated
579
;          if CARRY=1 cluster out of range
580
; Note   : if cluster=0 it's changed to read rootdir
581
;-----------------------------------------------------------
582
    push  eax ecx
583
 
584
    mov   [fat16_root],0
585
    cmp   eax,[LAST_CLUSTER]
586
    ja    gdc_error             ; too big cluster number, something is wrong
587
    cmp   eax,2
588
    jnb   gdc_cluster
589
 
590
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
591
    cmp   [fat_type],16
592
    jne   gdc_cluster
593
    mov   eax,[ROOT_START]
594
    mov   ecx,[ROOT_SECTORS]    ; Note: not cluster size
595
    mov   [fat16_root],1        ; flag for fat16 rootdir
596
    jmp   gdc_read
597
 
598
  gdc_cluster:
599
    sub   eax,2
600
    mov   ecx,[SECTORS_PER_CLUSTER]
601
    imul  eax,ecx
602
    add   eax,[DATA_START]
603
 
604
  gdc_read:
605
    test  esi,esi               ; first wanted block
606
    je    gdcl1                 ; yes, skip count is 0
607
    dec   esi
608
    jmp   gdcl2
609
 
610
  gdcl1:
611
    call  hd_read
74 mario79 612
    cmp  [hd_error],0
613
    jne  gdc_error
614
 
1 ha 615
    add   ebx,512               ; update pointer
616
    dec   edx
617
 
618
  gdcl2:
619
    test  edx,edx               ; is all read?
620
    je    out_of_read
621
 
622
    inc   eax                   ; next sector
623
    dec   ecx
624
    jnz   gdc_read
625
 
626
  out_of_read:
627
    pop   ecx eax
628
    clc
629
    ret
630
 
631
  gdc_error:
632
    pop   ecx eax
633
    stc
634
    ret
635
 
636
 
637
set_data_cluster:
638
;-----------------------------------------------------------
639
; input  : EAX = cluster
640
;          EBX = pointer to buffer
641
; output : if CARRY=0 ok
642
;          if CARRY=1 cluster out of range
643
;-----------------------------------------------------------
644
    push  eax ebx edx
645
 
646
    cmp   eax,[LAST_CLUSTER]
647
    ja    sdc_error             ; too big cluster number, something is wrong
648
    sub   eax,2
649
    jb    sdc_error             ; don't allow rootdir write
650
 
651
    mov   edx,[SECTORS_PER_CLUSTER]
652
    imul  eax,edx
653
    add   eax,[DATA_START]
654
 
655
  sdc_write:
656
    call  hd_write
74 mario79 657
    cmp   [hd_error],0
658
    jne   sdc_error
659
 
1 ha 660
    add   ebx,512               ; update pointer
661
    inc   eax
662
    dec   edx
663
    jnz   sdc_write
664
    pop   edx ebx eax
665
    clc
666
    ret
667
 
668
  sdc_error:
669
    pop   edx ebx eax
670
    stc
671
    ret
672
 
673
 
674
get_cluster_of_a_path:
675
;---------------------------------------------------------
676
; input  : EBX = pointer to a path string
677
;          (example: the path "/files/data/document" become
678
;                             "files......data.......document...0"
679
;          '.' = space char
680
;          '0' = char(0) (ASCII=0) !!! )
681
; output : if (CARRY=1) -> ERROR in the PATH
682
;          if (CARRY=0) -> EAX=cluster
683
;---------------------------------------------------------
684
    push  ebx edx
685
 
686
    mov   eax,[ROOT_CLUSTER]
687
    mov   edx,ebx
688
 
689
search_end_of_path:
690
    cmp   byte [edx],0
691
    je    found_end_of_path
692
 
693
    inc   edx ; '/'
694
    mov   ebx,edx
695
    call  analyze_directory
696
    jc    directory_not_found
697
 
698
    mov   eax,[ebx+20-2]        ; read the HIGH 16bit cluster field
699
    mov   ax,[ebx+26]           ; read the LOW 16bit cluster field
700
    and   eax,[fatMASK]
701
    add   edx,11                ; 8+3 (name+extension)
702
    jmp   search_end_of_path
703
 
704
found_end_of_path:
705
    pop   edx ebx
706
    clc                         ; no errors
707
    ret
708
 
709
directory_not_found:
710
    pop   edx ebx
711
    stc                         ; errors occour
712
    ret
713
 
714
 
715
bcd2bin:
716
;----------------------------------
717
; input  : AL=BCD number (eg. 0x11)
718
; output : AH=0
719
;          AL=decimal number (eg. 11)
720
;----------------------------------
721
    xor   ah,ah
722
    shl   ax,4
723
    shr   al,4
724
    aad
725
    ret
726
 
727
 
728
get_date_for_file:
729
;-----------------------------------------------------
730
; Get date from CMOS and pack day,month,year in AX
731
; DATE   bits  0..4   : day of month 0..31
732
;              5..8   : month of year 1..12
733
;              9..15  : count of years from 1980
734
;-----------------------------------------------------
735
    mov   al,0x7        ;day
736
    out   0x70,al
737
    in    al,0x71
738
    call  bcd2bin
739
    ror   eax,5
740
 
741
    mov   al,0x8        ;month
742
    out   0x70,al
743
    in    al,0x71
744
    call  bcd2bin
745
    ror   eax,4
746
 
747
    mov   al,0x9        ;year
748
    out   0x70,al
749
    in    al,0x71
750
    call  bcd2bin
751
    add   ax,20         ;because CMOS return only the two last
752
                        ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
753
    rol   eax,9         ;need the difference with 1980 (eg. 2001-1980)
754
    ret
755
 
756
 
757
get_time_for_file:
758
;-----------------------------------------------------
759
; Get time from CMOS and pack hour,minute,second in AX
760
; TIME   bits  0..4   : second (the low bit is lost)
761
;              5..10  : minute 0..59
762
;              11..15 : hour 0..23
763
;-----------------------------------------------------
764
    mov   al,0x0        ;second
765
    out   0x70,al
766
    in    al,0x71
767
    call  bcd2bin
768
    ror   eax,6
769
 
770
    mov   al,0x2        ;minute
771
    out   0x70,al
772
    in    al,0x71
773
    call  bcd2bin
774
    ror   eax,6
775
 
776
    mov   al,0x4        ;hour
777
    out   0x70,al
778
    in    al,0x71
779
    call  bcd2bin
780
    rol   eax,11
781
    ret
782
 
783
 
784
set_current_time_for_entry:
785
;-----------------------------------------------------
786
; Set current time/date for file entry
787
; input  : ebx = file entry pointer
788
;-----------------------------------------------------
789
    push  eax
790
    call  get_time_for_file     ; update files date/time
791
    mov   [ebx+22],ax
792
    call  get_date_for_file
793
    mov   [ebx+24],ax
794
    pop   eax
795
    ret
796
 
797
 
798
makedir:
799
;-----------------------------------------------------
800
; input  : eax = directory name
801
;          edx = path
802
; output : eax = 0 - ok
803
;                3 - unknown FS
804
;                5 - file not found
805
;                8 - disk full
806
;               10 - access denied
807
; Note   : can only make one directory at time
808
;-----------------------------------------------------
809
    cmp   [fat_type],0
810
    jnz   make_dir_fat_ok
811
    mov   eax,ERROR_UNKNOWN_FS
812
    ret
813
 
814
  make_dir_fat_ok:
815
;    call  reserve_hd1
816
 
817
    pushad
818
 
819
    mov   ebx,edx
820
    call  get_cluster_of_a_path
821
    jnc   make_dir_found_path
74 mario79 822
    cmp   [hd_error],0
823
    jne   make_dir_error_1
1 ha 824
 
825
  make_dir_path_not_found:
826
    popad
827
    call  update_disk           ; write all of cache and fat to hd
74 mario79 828
    cmp   [hd_error],0
829
    jne   make_dir_error_2
830
 
1 ha 831
    mov   [hd1_status],0
832
    mov   eax,ERROR_FILE_NOT_FOUND
833
    ret
834
 
835
  make_dir_disk_full:
74 mario79 836
    cmp  [hd_error],0
837
    jne   make_dir_error_1
1 ha 838
    popad
839
    call  update_disk           ; write all of cache and fat to hd
74 mario79 840
    cmp   [hd_error],0
841
    jne   make_dir_error_2
842
 
1 ha 843
    mov   [hd1_status],0
844
    mov   eax,ERROR_DISK_FULL
845
    ret
846
 
847
  make_dir_already_exist:
74 mario79 848
    cmp  [hd_error],0
849
    jne   make_dir_error_1
1 ha 850
    mov   eax,[cluster]         ; directory cluster
851
    xor   edx,edx               ; free
852
    mov   [f_del],1
853
    call  set_FAT
74 mario79 854
    cmp  [hd_error],0
855
    jne   make_dir_error_1
856
 
1 ha 857
    mov   [f_del],0
858
 
859
    popad
860
    call  update_disk           ; write all of cache and fat to hd
74 mario79 861
  make_dir_error_2:
1 ha 862
    mov   [hd1_status],0
863
    mov   eax,ERROR_ACCESS_DENIED
864
    ret
865
 
74 mario79 866
  make_dir_error_1:
867
    popad
868
    jmp   make_dir_error_2
869
 
870
  make_dir_error_3:
871
    add  esp,4
872
    jmp   make_dir_error_1
873
 
1 ha 874
  make_dir_found_path:
875
    cmp   eax,[ROOT_CLUSTER]
876
    jnz   make_dir_not_root
877
    xor   eax,eax
878
 
879
  make_dir_not_root:
880
    mov   ecx,eax               ; directorys start cluster
881
    mov   word [NewDirEntry2+26],cx ; 16 bits low of cluster
882
    shr   ecx,16
883
    mov   word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16)
884
 
885
    push  eax                   ; save parent directory cluster
886
    mov   eax,2
887
    call  get_free_FAT
888
    mov   [cluster],eax         ; first free cluster
889
    pop   eax
890
    jc    make_dir_disk_full
891
 
892
    push  eax
893
    mov   eax,[cluster]         ; directory cluster
894
    mov   edx,[fatEND]          ; end for directory
895
    call  set_FAT
74 mario79 896
    cmp  [hd_error],0
897
    jne   make_dir_error_3
1 ha 898
    pop   eax
899
 
900
    mov   ebx,PUSHAD_EAX        ; dir name
901
    push  eax
902
    call  analyze_directory     ; check if directory already exist
74 mario79 903
    cmp   [hd_error],0
904
    jne   make_dir_error_1
905
 
1 ha 906
    pop   eax
907
    jnc   make_dir_already_exist ; need to free allocated cluster!
908
 
909
    call  analyze_directory_to_write
910
    jc    make_dir_already_exist ; need to free allocated cluster!
911
 
912
    mov   esi,PUSHAD_EAX        ; dir name
913
    mov   edi,ebx               ; pointer in buffer
914
    mov   ecx,11
915
    cld
916
    rep   movsb
917
 
918
    mov   dword [ebx+28],0      ; dir size is always 0
919
    mov   ecx,[cluster]
920
    mov   [ebx+26],cx           ; 16 bits low of cluster
921
    mov   word [NewDirEntry1+26],cx
922
    shr   ecx,16
923
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
924
    mov   word [NewDirEntry1+20],cx
925
    mov   byte [ebx+11],0x10    ; attribute = directory
926
 
927
    call  set_current_time_for_entry
928
    mov   ecx,[ebx+22]
929
    mov   dword [NewDirEntry1+22],ecx
930
    mov   dword [NewDirEntry2+22],ecx
931
 
932
    mov   ebx,buffer            ; save the directory name,length,cluster
933
    call  hd_write
74 mario79 934
    cmp   [hd_error],0
935
    jne   make_dir_error_1
1 ha 936
 
937
    mov   ecx,512/4
938
    xor   eax,eax
939
    mov   edi,buffer
940
    cld
941
    rep   stosd                 ; clear new directory cluster
942
 
943
    mov   eax,[cluster]         ; new directory cluster
944
    sub   eax,2
945
    mov   edx,[SECTORS_PER_CLUSTER]
946
    imul  eax,edx
947
    add   eax,[DATA_START]
948
    mov   ebx,buffer
949
    add   eax,edx               ; start from last sector
950
 
951
  dir_set_empty_directory:
952
    dec   eax                   ; next sector
953
    cmp   edx,1                 ; is first directory sector?
954
    jnz   not_first_sector      ; no. write empty sector
955
    mov   esi,NewDirEntry1
956
    mov   edi,buffer
957
    mov   ecx,64/4
958
    cld
959
    rep   movsd                 ; copy 2 first directory entrys "." and ".."
960
 
961
  not_first_sector:
962
    call  hd_write
74 mario79 963
    cmp   [hd_error],0
964
    jne   make_dir_error_1
965
 
1 ha 966
    dec   edx
967
    jnz   dir_set_empty_directory
968
 
969
    mov   ecx,-1                ; remove 1 cluster from free disk space
970
    call  add_disk_free_space
74 mario79 971
    cmp  [hd_error],0
972
    jne   make_dir_error_1
1 ha 973
 
974
    popad
975
    call  update_disk           ; write all of cache and fat to hd
74 mario79 976
    cmp   [hd_error],0
977
    jne   make_dir_error_2
1 ha 978
    mov   [hd1_status],0
979
    xor   eax,eax
980
    ret
981
 
982
 
983
removedir:
984
;-----------------------------------------------------
985
; input  : eax = file/directory name
986
;          edx = path
987
; output : eax = 0 - ok
988
;                3 - unknown FS
989
;                5 - file not found
990
;               10 - access denied
991
;-----------------------------------------------------
992
    cmp   [fat_type],0
993
    jnz   remove_dir_fat_ok
994
    mov   eax,ERROR_UNKNOWN_FS
995
    ret
996
 
997
  remove_dir_fat_ok:
998
;    call  reserve_hd1
999
 
1000
    push  edi
1001
    mov   edi,1                 ; allow directory remove
1002
    call  file_delete
74 mario79 1003
    cmp   [hd_error],0
1004
    jne   @f
1005
 
1 ha 1006
    pop   edi
1007
 
1008
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1009
  @@:
1 ha 1010
    mov   [hd1_status],0
1011
    ret
74 mario79 1012
 
1 ha 1013
 
1014
add_disk_free_space:
1015
;-----------------------------------------------------
1016
; input  : ecx = cluster count
1017
; Note   : negative = remove clusters from free space
1018
;          positive = add clusters to free space
1019
;-----------------------------------------------------
1020
    test  ecx,ecx               ; no change
1021
    je    add_dfs_no
1022
    cmp   [fat_type],32         ; free disk space only used by fat32
1023
    jne   add_dfs_no
1024
 
1025
    push  eax ebx
1026
    mov   eax,[ADR_FSINFO]
1027
    mov   ebx,buffer
1028
    call  hd_read
74 mario79 1029
    cmp  [hd_error],0
1030
    jne  add_not_fs
1031
 
1 ha 1032
    cmp   dword [ebx+0x1fc],0xaa550000 ; check sector id
1033
    jne   add_not_fs
1034
 
1035
    add   [ebx+0x1e8],ecx
1036
    call  hd_write
74 mario79 1037
    cmp   [hd_error],0
1038
    jne   add_not_fs
1 ha 1039
 
1040
  add_not_fs:
1041
    pop   ebx eax
1042
 
1043
  add_dfs_no:
1044
    ret
1045
 
1046
 
1047
file_append:
1048
;-----------------------------------------------------
1049
; input  : eax = file name
1050
;          edx = path
1051
;          ecx = pointer to buffer
1052
;          ebx = bytes to write (0 = truncate file)
1053
;          esi = start position (-1 = end of file)
1054
; output : eax = 0 - ok
1055
;                3 - unknown FS
1056
;                5 - file not found
1057
;                6 - end of file
1058
;                8 - disk full
1059
;                9 - fat table corrupted
1060
;               10 - access denied
1061
;          ebx = bytes written
1062
;-----------------------------------------------------
1063
    cmp   [fat_type],0
1064
    jnz   append_fat_ok
1065
    mov   eax,ERROR_UNKNOWN_FS
1066
    ret
1067
 
1068
  append_fat_ok:
1069
;    call  reserve_hd1
1070
 
1071
    pushad
1072
 
1073
    mov   ebx,edx
1074
    call  get_cluster_of_a_path
1075
    jc    append_not_found
1076
 
1077
    mov   ebx,PUSHAD_EAX        ; file name
1078
    call  analyze_directory
1079
    jc    append_not_found
1080
 
1081
    mov   [sector_tmp],eax
1082
    mov   [entry_pos],ebx
1083
 
1084
    test  byte [ebx+11],0x10    ; is it directory?
1085
    jnz   append_access         ; yes
1086
 
1087
    mov   ecx,[ebx+28]          ; file size
1088
    mov   edi,PUSHAD_ESI        ; write position
1089
    cmp   edi,-1                ; -1 = eof
1090
    jnz   append_inside_file
1091
    mov   edi,ecx               ; file size
1092
 
1093
  append_inside_file:
1094
    cmp   edi,ecx               ; start above old file size?
1095
    ja    append_eof            ; yes
1096
 
1097
    mov   [old_filesize],ecx
1098
    mov   [new_filepos],edi
1099
 
1100
    mov   ecx,PUSHAD_EBX        ; bytes to write
1101
    test  ecx,ecx               ; truncate?
1102
    jz    append_truncate       ; yes
1103
 
1104
    mov   [bytes2write],ecx     ; bytes to write
1105
    mov   esi,PUSHAD_ECX        ; pointer to buffer
1106
    mov   eax,[ebx+20-2]        ; FAT entry
1107
    mov   ax,[ebx+26]
1108
    and   eax,[fatMASK]
1109
    jnz   append_find_pos       ; first cluster <> 0
1110
 
1111
    mov   eax,2
1112
    call  get_free_FAT
1113
    jc    append_disk_full
1114
    mov   ecx,eax               ; set files first cluster
1115
    mov   [ebx+26],cx           ; 16 bits low of cluster
1116
    shr   ecx,16
1117
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
1118
    mov   edx,[fatEND]          ; new end for cluster chain
1119
    call  set_FAT
74 mario79 1120
    cmp  [hd_error],0
1121
    jne   append_access
1 ha 1122
 
1123
    push  eax                   ; save first cluster
1124
    mov   eax,[sector_tmp]
1125
    mov   ebx,buffer
1126
    call  hd_write              ; write new file entry back to disk
74 mario79 1127
    cmp   [hd_error],0
1128
    jne   append_access_1
1129
 
1 ha 1130
    pop   eax
1131
 
1132
  append_remove_free:
1133
    mov   ecx,-1                ; remove 1 cluster from free disk space
1134
    call  add_disk_free_space   ; Note: uses buffer
74 mario79 1135
    cmp  [hd_error],0
1136
    jne   append_access
1 ha 1137
 
1138
  append_found_cluster:
1139
    mov   [cluster],eax
1140
    sub   eax,2
1141
    mov   ecx,[SECTORS_PER_CLUSTER]
1142
    imul  eax,ecx
1143
    add   eax,[DATA_START]
1144
    xor   edi,edi
1145
 
1146
  append_new_sector:
74 mario79 1147
    cmp   [hd_error],0
1148
    jne   append_access
1 ha 1149
    push  ecx
1150
    mov   ecx,[bytes2write]     ; bytes left in buffer
1151
    mov   ebx,512
1152
    sub   ebx,edi               ; bytes left in sector
1153
    cmp   ecx,ebx
1154
    jb    append_bytes_ok
1155
    mov   ecx,ebx
1156
 
1157
  append_bytes_ok:
1158
    cmp   ecx,512               ; overwrite full sector?
1159
    jz    append_full_sector    ; yes
1160
    mov   ebx,buffer            ; overwrite part of sector
1161
    call  hd_read               ; read old sector
74 mario79 1162
    cmp  [hd_error],0
1163
    jne  append_access_1
1 ha 1164
 
1165
  append_full_sector:
1166
    sub   [bytes2write],ecx
1167
    add   [new_filepos],ecx
1168
    add   edi,buffer
1169
    cld
1170
    rep   movsb
1171
    pop   ecx
1172
 
1173
    mov   ebx,buffer
1174
    call  hd_write
74 mario79 1175
    cmp   [hd_error],0
1176
    jne   append_access
1177
 
1 ha 1178
    cmp   [bytes2write],0       ; is all done?
1179
    jz    append_done
1180
    xor   edi,edi
1181
    inc   eax
1182
    dec   ecx
1183
    jnz   append_new_sector
1184
 
1185
    mov   eax,[cluster]
1186
    call  get_FAT
74 mario79 1187
    cmp   [hd_error],0
1188
    jne   append_access
1189
 
1 ha 1190
    cmp   eax,2
1191
    jb    append_fat
1192
    cmp   eax,[LAST_CLUSTER]
1193
    jbe   append_found_cluster
1194
 
1195
  append_alloc_cluster:
1196
    mov   eax,2                 ; ToDo: use temp array to keep track
1197
    call  get_free_FAT          ;       of last free cluster
1198
    jc    append_disk_full
1199
    push  eax                   ; save new cluster
1200
    mov   edx,[fatEND]          ; new end for cluster chain
1201
    call  set_FAT
74 mario79 1202
    cmp  [hd_error],0
1203
    jne  append_access_1
1204
 
1 ha 1205
    mov   edx,eax
1206
    mov   eax,[cluster]
1207
    mov   [f_del],1
1208
    call  set_FAT               ; update previous cluster
74 mario79 1209
    cmp  [hd_error],0
1210
    jne  append_access_1
1211
 
1 ha 1212
    mov   [f_del],0
1213
    pop   eax
1214
    jmp   append_remove_free
1215
 
1216
  append_find_pos:
1217
    call  find_filepos
1218
    mov   [cluster],ebx
1219
    jnc   append_new_sector
1220
    test  edi,edi
1221
    jz    append_alloc_cluster
1222
 
1223
  append_fat:
1224
    mov   eax,ERROR_FAT_TABLE
1225
    jmp   append_ret_code
74 mario79 1226
 
1 ha 1227
  append_disk_full:
74 mario79 1228
    cmp  [hd_error],0
1229
    jne  append_access
1 ha 1230
    mov   eax,ERROR_DISK_FULL
1231
    jmp   append_ret_code
1232
 
1233
  append_done:
1234
    xor   eax,eax
1235
 
1236
  append_ret_code:
1237
    mov   PUSHAD_EAX,eax        ; return code
1238
 
1239
    mov   eax,[sector_tmp]      ; update directory entry
1240
    mov   ebx,buffer
1241
    call  hd_read
74 mario79 1242
    cmp  [hd_error],0
1243
    jne  append_access
1244
 
1 ha 1245
    mov   ebx,[entry_pos]
1246
    mov   ecx,[new_filepos]
1247
    cmp   ecx,[old_filesize]    ; is file pos above old size?
1248
    jbe   append_size_ok        ; no
1249
    mov   [ebx+28],ecx          ; new file size
1250
 
1251
  append_size_ok:
1252
    call  set_current_time_for_entry
1253
    mov   ebx,buffer
1254
    call  hd_write              ; write new file entry back to disk
74 mario79 1255
    cmp   [hd_error],0
1256
    jne   append_access
1 ha 1257
 
1258
    sub   ecx,PUSHAD_ESI        ; start position
1259
    mov   PUSHAD_EBX,ecx        ; bytes written
1260
    popad
1261
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1262
    cmp   [hd_error],0
1263
    jne   append_access_2
1264
 
1 ha 1265
    mov   [hd1_status],0
1266
    ret
1267
 
1268
  append_eof:
1269
    popad
1270
    mov   [hd1_status],0
1271
    xor   ebx,ebx
1272
    mov   eax,ERROR_END_OF_FILE
1273
    ret
1274
 
1275
  append_not_found:
74 mario79 1276
    cmp  [hd_error],0
1277
    jne   append_access
1 ha 1278
    popad
1279
    mov   [hd1_status],0
1280
    xor   ebx,ebx
1281
    mov   eax,ERROR_FILE_NOT_FOUND
74 mario79 1282
    ret
1283
  append_access_1:
1284
    add   esp,4
1 ha 1285
  append_access:
1286
    popad
74 mario79 1287
  append_access_2:
1 ha 1288
    mov   [hd1_status],0
1289
    xor   ebx,ebx
1290
    mov   eax,ERROR_ACCESS_DENIED
1291
    ret
1292
 
1293
  append_truncate:
1294
    mov   edx,[ebx+20-2]        ; FAT entry
1295
    mov   dx,[ebx+26]
1296
    and   edx,[fatMASK]
1297
    mov   [ebx+28],edi          ; set new file size
1298
    test  edi,edi               ; 0 length file?
1299
    jnz   truncate_save_size    ; no
1300
    mov   [ebx+20],di           ; FAT entry = 0
1301
    mov   [ebx+26],di
1302
 
1303
  truncate_save_size:
1304
    call  set_current_time_for_entry
1305
    mov   ebx,buffer
1306
    call  hd_write
74 mario79 1307
    cmp   [hd_error],0
1308
    jne   append_access
1309
 
1 ha 1310
    mov   eax,edx               ; first cluster
1311
    test  edi,edi               ; 0 length file?
1312
    jz    truncate_clear_chain
1313
 
1314
    imul  esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes
1315
 
1316
  truncate_new_cluster:
1317
    cmp   eax,2                 ; incorrect fat chain?
1318
    jb    truncate_eof          ; yes
1319
    cmp   eax,[fatRESERVED]     ; is it end of file?
1320
    jnb   truncate_eof          ; yes
1321
    sub   edi,esi
1322
    jbe   truncate_pos_found
1323
    call  get_FAT               ; get next cluster
74 mario79 1324
    cmp   [hd_error],0
1325
    jne   append_access
1326
 
1 ha 1327
    jmp   truncate_new_cluster
1328
 
1329
  truncate_pos_found:
1330
    mov   edx,[fatEND]          ; new end for cluster chain
1331
    mov   [f_del],1
1332
    call  set_FAT
74 mario79 1333
    cmp  [hd_error],0
1334
    jne  append_access
1335
 
1 ha 1336
    mov   [f_del],0
1337
    mov   eax,edx               ; clear rest of chain
1338
 
1339
  truncate_clear_chain:
1340
    call  clear_cluster_chain
74 mario79 1341
    cmp  [hd_error],0
1342
    jne  append_access
1 ha 1343
 
1344
  truncate_eof:
1345
    popad
1346
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1347
    cmp   [hd_error],0
1348
    jne   append_access_2
1349
 
1 ha 1350
    mov   [hd1_status],0
1351
    xor   ebx,ebx
1352
    xor   eax,eax
1353
    ret
1354
 
1355
 
1356
find_filepos:
1357
;-----------------------------------------------------
1358
; input  : eax = first cluster
1359
;          edi = bytes to skip over (start position)
1360
; output : if CARRY=0 file position found
1361
;          if CARRY=1 end of file found
1362
;          eax = current file sector
1363
;          ebx = last cluster
1364
;          ecx = sector count in last cluster
1365
;          edi = bytes to skip over (sector position)
1366
;-----------------------------------------------------
1367
    push  esi
1368
    mov   ecx,[SECTORS_PER_CLUSTER]
1369
    imul  esi,ecx,512           ; esi = cluster size in bytes
1370
    mov   ebx,eax
1371
 
1372
  filepos_new_cluster:
1373
    cmp   eax,2                 ; incorrect fat chain?
1374
    jb    filepos_eof           ; yes
1375
    cmp   eax,[fatRESERVED]     ; is it end of file?
1376
    jnb   filepos_eof           ; yes
1377
 
1378
    mov   ebx,eax
1379
    cmp   edi,esi               ; skip over full cluster?
1380
    jb    filepos_cluster_ok    ; no
1381
 
1382
    sub   edi,esi
1383
    call  get_FAT               ; get next cluster
74 mario79 1384
    cmp   [hd_error],0
1385
    jne   filepos_eof
1386
 
1 ha 1387
    jmp   filepos_new_cluster
1388
 
1389
  filepos_cluster_ok:
1390
    sub   eax,2
1391
    imul  eax,ecx
1392
    add   eax,[DATA_START]
1393
 
1394
  filepos_new_sector:
1395
    cmp   edi,512               ; skip over full sector?
1396
    jb    filepos_sector_ok     ; no
1397
    sub   edi,512
1398
    inc   eax
1399
    dec   ecx
1400
    jnz   filepos_new_sector
1401
 
1402
  filepos_eof:
1403
    pop   esi
1404
    stc
1405
    ret
1406
 
1407
  filepos_sector_ok:
1408
    pop   esi
1409
    clc
1410
    ret
1411
 
1412
 
1413
file_write:
1414
;--------------------------------------------------------------------------
1415
;   INPUT : user-reg  register-in-this  meaning      symbol-in-this-routine
1416
;
1417
;            EAX        EDI            system call to write    /
1418
;            EBX        EAX   (PAR0)   pointer to file-name    PAR0
1419
;            EDX        ECX   (PAR1)   pointer to buffer       PAR1
1420
;            ECX        EBX   (PAR2)   file size               PAR2
1421
;            ESI        EDX   (PAR3)   pointer to path         PAR3
1422
;
1423
; output : eax = 0 - ok
1424
;                3 - unknown FS
1425
;                5 - file not found
1426
;                8 - disk full
1427
;               10 - access denied
1428
;--------------------------------------------------------------------------
1429
    cmp   [fat_type],0
1430
    jnz   fat_ok_for_writing
1431
    mov   eax,ERROR_UNKNOWN_FS
1432
    ret
1433
 
1434
  fat_ok_for_writing:
1435
;    call  reserve_hd1
1436
 
1437
    pushad
1438
 
1439
    xor   edi,edi               ; don't allow directory remove
1440
    call  file_delete           ; try to delete the file first
74 mario79 1441
    cmp   [hd_error],0
1442
    jne   exit_write_access_1
1443
 
1 ha 1444
    test  eax,eax
1445
    jz    old_deleted           ; deleted ok
1446
    cmp   eax,ERROR_FILE_NOT_FOUND
1447
    jnz   exit_write_access     ; it exist but can't delete
1448
 
1449
  old_deleted:
1450
    mov   ebx,PUSHAD_EDX
1451
    call  get_cluster_of_a_path
1452
    jnc   found_directory_for_writing
74 mario79 1453
    cmp   [hd_error],0
1454
    jne   exit_write_access
1 ha 1455
 
1456
  exit_writing_with_error:
1457
    popad
1458
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1459
    cmp   [hd_error],0
1460
    jne   exit_write_access_2
1461
 
1 ha 1462
    mov   [hd1_status],0
1463
    mov   eax,ERROR_FILE_NOT_FOUND
1464
    ret
1465
 
1466
  exit_writing_disk_full_clear:
74 mario79 1467
    cmp  [hd_error],0
1468
    jne  exit_write_access_1
1 ha 1469
    mov   eax,[sector_tmp]
1470
    mov   ebx,buffer
1471
    call  hd_read               ; read directory sector
74 mario79 1472
    cmp  [hd_error],0
1473
    jne  exit_write_access_1
1474
 
1 ha 1475
    mov   edx,[entry_pos]
1476
    mov   byte [edx],0xe5       ; mark as deleted
1477
    call  hd_write
74 mario79 1478
    cmp   [hd_error],0
1479
    jne   exit_write_access_1
1480
 
1 ha 1481
    mov   eax,[edx+20-2]        ; FAT entry
1482
    mov   ax,[edx+26]
1483
    and   eax,[fatMASK]
1484
    call  clear_cluster_chain
1485
 
1486
  exit_writing_disk_full:
74 mario79 1487
    cmp  [hd_error],0
1488
    jne  exit_write_access_1
1 ha 1489
    popad
1490
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1491
    cmp   [hd_error],0
1492
    jne   exit_write_access_2
1 ha 1493
    mov   [hd1_status],0
1494
    mov   eax,ERROR_DISK_FULL
1495
    ret
1496
 
1497
  exit_write_access:
1498
    popad
1499
    call  update_disk           ; write all of cache and fat to hd
1500
    mov   [hd1_status],0
1501
    mov   eax,ERROR_ACCESS_DENIED
1502
    ret
1503
 
74 mario79 1504
  exit_write_access_1:
1505
    popad
1506
  exit_write_access_2:
1507
    mov   [hd1_status],0
1508
    mov   eax,ERROR_ACCESS_DENIED
1509
    ret
1510
 
1 ha 1511
found_directory_for_writing:
1512
    call  analyze_directory_to_write
1513
    jc    exit_writing_disk_full
1514
 
1515
    mov   [sector_tmp],eax
1516
    mov   [entry_pos],ebx
1517
    push  eax                   ; save directory sector
1518
    mov   eax,2
1519
    call  get_free_FAT
1520
    mov   [cluster],eax         ; first free cluster
1521
    pop   eax
1522
    jc    exit_writing_disk_full
1523
 
1524
    mov   esi,PUSHAD_EAX        ; file name
1525
    mov   edi,ebx               ; pointer in buffer
1526
    mov   ecx,11
1527
    cld
1528
    rep   movsb
1529
 
1530
    mov   esi,PUSHAD_EBX        ; file size (bytes left)
1531
    mov   [ebx+28],esi          ; file size
1532
    mov   ecx,[cluster]
1533
    mov   [ebx+26],cx           ; 16 bits low of cluster
1534
    shr   ecx,16
1535
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
1536
    mov   byte [ebx+11],0x20    ; attribute = archive
1537
 
1538
    call  set_current_time_for_entry
1539
 
1540
    mov   ebx,buffer            ; save the directory name,length,cluster
1541
    call  hd_write
74 mario79 1542
    cmp   [hd_error],0
1543
    jne   exit_write_access_1
1 ha 1544
 
1545
    imul  edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes
1546
    xor   ecx,ecx               ; cluster count
1547
    mov   ebx,PUSHAD_ECX        ; ebx = buffer
1548
 
1549
hd_new_block_write:
1550
 
1551
    mov   eax,[cluster]         ; eax = block
1552
    call  set_data_cluster
74 mario79 1553
    cmp   [hd_error],0
1554
    jne   exit_write_access_1
1 ha 1555
 
1556
    sub   esi,edi               ; sub wrote bytes
1557
    jbe   file_saved_OK         ; end if all done
1558
    add   ebx,edi               ; update buffer position
1559
 
1560
    inc   eax
1561
    call  get_free_FAT          ; next free in FAT
1562
    jc    exit_writing_disk_full_clear
1563
 
1564
    mov   edx,eax
1565
    xchg  eax,[cluster]         ; get old cluster and save new cluster
1566
    call  set_FAT               ; add it in cluster chain
74 mario79 1567
    cmp  [hd_error],0
1568
    jne   exit_write_access_1
1569
 
1 ha 1570
    dec   ecx                   ; update cluster count
1571
    jmp   hd_new_block_write
1572
 
1573
file_saved_OK:
1574
 
1575
    mov   edx,[fatEND]          ; new end for cluster chain
1576
    call  set_FAT
74 mario79 1577
    cmp  [hd_error],0
1578
    jne   exit_write_access_1
1579
 
1 ha 1580
    dec   ecx                   ; update cluster count
1581
 
1582
    call  add_disk_free_space   ; remove clusters from free disk space
74 mario79 1583
    cmp  [hd_error],0
1584
    jne   exit_write_access_1
1 ha 1585
 
1586
    popad
1587
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1588
    cmp   [hd_error],0
1589
    jne   exit_write_access_2
1 ha 1590
    mov   [hd1_status],0
1591
    xor   eax,eax
1592
    ret
1593
 
1594
 
1595
file_read:
1596
;--------------------------------------------------------------------------
1597
;   INPUT :  user-register register-in-this  meaning         symbol-in-this
1598
;
1599
;            EAX           EDI               system call to write   /
1600
;            EBX           EAX   (PAR0)      pointer to file-name   PAR0
1601
;            EDX           ECX   (PAR1)      pointer to buffer      PAR1
1602
;            ECX           EBX   (PAR2)   vt file blocks to read    PAR2
1603
;            ESI           EDX   (PAR3)      pointer to path        PAR3
1604
;            EDI           ESI            vt first 512 block to read
1605
;                          EDI               if 0 - read root
1606
;
1607
; output : eax = 0 - ok
1608
;                3 - unknown FS
1609
;                5 - file not found
1610
;                6 - end of file
1611
;                9 - fat table corrupted
74 mario79 1612
;               10 - access denied
1 ha 1613
;          ebx = size of file/directory
1614
;--------------------------------------------------------------------------
1615
    cmp   [fat_type],0
1616
    jnz   fat_ok_for_reading
1617
    xor   ebx,ebx
1618
    mov   eax,ERROR_UNKNOWN_FS
63 halyavin 1619
    mov   [hd1_status], ebx
1 ha 1620
    ret
1621
 
1622
  fat_ok_for_reading:
1623
;    call  reserve_hd1
1624
 
1625
    pushad
1626
 
1627
    mov   ebx,edx
1628
    call  get_cluster_of_a_path
1629
    jc    file_to_read_not_found
1630
 
1631
    test  edi,edi               ; read rootdir
1632
    jne   no_read_root
1633
 
1634
    xor   eax,eax
1635
    call  get_dir_size          ; return rootdir size
74 mario79 1636
    cmp   [hd_error],0
1637
    jne   file_access_denied
1638
 
1 ha 1639
    mov   [file_size],eax
1640
    mov   eax,[ROOT_CLUSTER]
1641
    jmp   file_read_start
1642
 
1643
  no_read_root:
1644
    mov   ebx,PUSHAD_EAX        ; file name
1645
    call  analyze_directory
1646
    jc    file_to_read_not_found
1647
 
1648
    mov   eax,[ebx+28]          ; file size
1649
    test  byte [ebx+11],0x10    ; is it directory?
1650
    jz    read_set_size         ; no
1651
 
1652
    mov   eax,[ebx+20-2]        ; FAT entry
1653
    mov   ax,[ebx+26]
1654
    and   eax,[fatMASK]
1655
    call  get_dir_size
74 mario79 1656
    cmp   [hd_error],0
1657
    jne   file_access_denied
1 ha 1658
 
1659
  read_set_size:
1660
    mov   [file_size],eax
1661
 
1662
    mov   eax,[ebx+20-2]        ; FAT entry
1663
    mov   ax,[ebx+26]
1664
    and   eax,[fatMASK]
1665
 
1666
  file_read_start:
1667
    mov   ebx,PUSHAD_ECX        ; pointer to buffer
1668
    mov   edx,PUSHAD_EBX        ; file blocks to read
1669
    mov   esi,PUSHAD_ESI        ; first 512 block to read
1670
 
1671
  file_read_new_cluster:
1672
    call  get_data_cluster
1673
    jc    file_read_eof         ; end of file or cluster out of range
1674
 
1675
    test  edx,edx               ; is all read?
1676
    je    file_read_OK          ; yes
1677
 
1678
    call  get_FAT               ; get next cluster
74 mario79 1679
    cmp   [hd_error],0
1680
    jne   file_access_denied
1681
 
1 ha 1682
    cmp   eax,[fatRESERVED]     ; end of file
1683
    jnb   file_read_eof
1684
    cmp   eax,2                 ; incorrect fat chain
1685
    jnb   file_read_new_cluster
1686
 
1687
    popad
1688
    mov   [hd1_status],0
1689
    mov   ebx,[file_size]
1690
    mov   eax,ERROR_FAT_TABLE
1691
    ret
1692
 
1693
  file_read_eof:
74 mario79 1694
    cmp   [hd_error],0
1695
    jne   file_access_denied
1 ha 1696
    popad
1697
    mov   [hd1_status],0
1698
    mov   ebx,[file_size]
1699
    mov   eax,ERROR_END_OF_FILE
1700
    ret
1701
 
1702
  file_read_OK:
1703
    popad
1704
    mov   [hd1_status],0
1705
    mov   ebx,[file_size]
1706
    xor   eax,eax
1707
    ret
1708
 
1709
  file_to_read_not_found:
74 mario79 1710
    cmp   [hd_error],0
1711
    jne   file_access_denied
1 ha 1712
    popad
1713
    mov   [hd1_status],0
1714
    xor   ebx,ebx
1715
    mov   eax,ERROR_FILE_NOT_FOUND
1716
    ret
1717
 
74 mario79 1718
  file_access_denied:
1719
    popad
1720
    mov   [hd1_status],0
1721
    xor   ebx,ebx
1722
    mov   eax,ERROR_ACCESS_DENIED
1723
    ret
1 ha 1724
 
1725
get_dir_size:
1726
;-----------------------------------------------------
1727
; input  : eax = first cluster (0=rootdir)
1728
; output : eax = directory size in bytes
1729
;-----------------------------------------------------
1730
    push  edx
1731
    xor   edx,edx               ; count of directory clusters
1732
    test  eax,eax
1733
    jnz   dir_size_next
1734
 
1735
    mov   eax,[ROOT_SECTORS]
1736
    shl   eax,9                 ; fat16 rootdir size in bytes
1737
    cmp   [fat_type],16
1738
    je    dir_size_ret
1739
    mov   eax,[ROOT_CLUSTER]
1740
 
1741
  dir_size_next:
1742
    cmp   eax,2                 ; incorrect fat chain
1743
    jb    dir_size_end
1744
    cmp   eax,[fatRESERVED]     ; end of directory
1745
    ja    dir_size_end
1746
    call  get_FAT               ; get next cluster
74 mario79 1747
    cmp   [hd_error],0
1748
    jne   dir_size_ret
1749
 
1 ha 1750
    inc   edx
1751
    jmp   dir_size_next
1752
 
1753
  dir_size_end:
1754
    imul  eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
1755
    imul  eax,edx
1756
 
1757
  dir_size_ret:
1758
    pop   edx
1759
    ret
1760
 
1761
 
1762
file_delete:
1763
;-----------------------------------------------------
1764
; input  : eax = file/directory name
1765
;          edx = path
1766
;          edi = 1 - allow directory remove else don't remove directory
1767
; output : eax = 0 - ok
1768
;                3 - unknown FS
1769
;                5 - file not found
1770
;               10 - access denied
1771
;-----------------------------------------------------
1772
    cmp   [fat_type],0
1773
    jnz   file_del_fat_ok
1774
    mov   eax,ERROR_UNKNOWN_FS
1775
    ret
1776
 
1777
  file_del_fat_ok:
1778
    pushad
1779
 
1780
    mov   ebx,edx
1781
    call  get_cluster_of_a_path
1782
    jc    file_to_delete_not_found
1783
 
1784
    mov   ebx,PUSHAD_EAX        ; file/directory name
1785
    call  analyze_directory
1786
    jc    file_to_delete_not_found
1787
 
1788
    test  byte [ebx+11],0x10    ; is it directory?
1789
    jz    delete_notdir         ; no. it's file
1790
    cmp   edi,1                 ; allow directory remove
1791
    jnz   delete_no_access      ; no
1792
 
1793
    push  eax                   ; save directory sector
1794
    mov   eax,[ebx+20-2]        ; first cluster of file
1795
    mov   ax,[ebx+26]           ; 0 length files start cluster = 0
1796
    and   eax,[fatMASK]
1797
    xor   ebp,ebp               ; counter for directory deepnes
1798
    call  clear_directory
1799
    pop   eax
1800
    jc    delete_no_access
1801
 
1802
    push  ebx                   ; save directory pointer in buffer
1803
    mov   ebx,buffer
1804
    call  hd_read               ; read directory sector
74 mario79 1805
    cmp  [hd_error],0
1806
    jne  delete_no_access_1
1 ha 1807
    pop   ebx
1808
 
1809
  delete_notdir:
1810
    call  delete_entry_name
74 mario79 1811
    cmp   [hd_error],0
1812
    jne   delete_no_access
1813
 
1 ha 1814
    mov   eax,ecx               ; first cluster of file
1815
    call  clear_cluster_chain
74 mario79 1816
    cmp   [hd_error],0
1817
    jne   delete_no_access
1818
 
1 ha 1819
    popad
1820
    xor   eax,eax
1821
    ret
1822
 
74 mario79 1823
  delete_no_access_1:
1824
     add esp,4
1 ha 1825
  delete_no_access:
1826
    popad
1827
    mov   eax,ERROR_ACCESS_DENIED
1828
    ret
1829
 
1830
  file_to_delete_not_found:
74 mario79 1831
    cmp  [hd_error],0
1832
    jne  delete_no_access
1 ha 1833
    popad
1834
    mov   eax,ERROR_FILE_NOT_FOUND
1835
    ret
1836
 
1837
 
1838
clear_cluster_chain:
1839
;-----------------------------------------------------
1840
; input  : eax = first cluster
1841
;-----------------------------------------------------
1842
    push  eax ecx edx
1843
    xor   ecx,ecx               ; cluster count
1844
    mov   [f_del],1             ; delete on
1845
 
1846
  clean_new_chain:
1847
    cmp   eax,[LAST_CLUSTER]    ; end of file
1848
    ja    delete_OK
1849
    cmp   eax,2                 ; unfinished fat chain or zero length file
1850
    jb    delete_OK
1851
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1852
    jz    delete_OK
1853
 
1854
    xor   edx,edx
1855
    call  set_FAT               ; clear fat entry
74 mario79 1856
    cmp  [hd_error],0
1857
    jne  access_denied_01
1858
 
1 ha 1859
    inc   ecx                   ; update cluster count
1860
    mov   eax,edx               ; old cluster
1861
    jmp   clean_new_chain
1862
 
1863
  delete_OK:
1864
    call  add_disk_free_space   ; add clusters to free disk space
74 mario79 1865
  access_denied_01:
1 ha 1866
    mov   [f_del],0
1867
    pop   edx ecx eax
1868
    ret
1869
 
1870
 
1871
clear_directory:
1872
;-----------------------------------------------------
1873
; input  : eax = directory cluster
1874
;          ebp = directory deepnes
1875
; Note   : use recursive call
1876
;-----------------------------------------------------
1877
    pushad
1878
    inc   ebp
1879
    cmp   ebp,64                ; if over 63 directory deep
1880
    jnb   clear_error           ; something must be wrong
1881
 
1882
  clear_new_cluster:
1883
    cmp   eax,[LAST_CLUSTER]
1884
    ja    clear_end
1885
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1886
    jz    clear_end
1887
    mov   esi,eax               ; esi = current directory cluster
1888
    sub   eax,2
1889
    jb    clear_end
1890
    mov   ecx,[SECTORS_PER_CLUSTER]
1891
    imul  eax,ecx
1892
    add   eax,[DATA_START]
1893
 
1894
  clear_new_sector:
1895
    mov   edi,eax               ; edi = current directory sector
1896
    mov   ebx,deltree_buffer
1897
    call  hd_read
74 mario79 1898
    cmp  [hd_error],0
1899
    jne  clear_error
1900
 
1 ha 1901
    mov   edx,512/32            ; count of dir entrys per sector = 16
1902
 
1903
  clear_analyze:
1904
    mov   al,[ebx+11]           ; file attribute
1905
    and   al,0xf
1906
    cmp   al,0xf
1907
    je    clear_long_filename
1908
 
1909
    cmp   byte [ebx],'.'        ; parent or current directory
1910
    je    clear_next_entry
1911
    cmp   byte [ebx],0xe5       ; deleted
1912
    je    clear_next_entry
1913
    cmp   byte [ebx],0          ; empty
1914
    je    clear_write_last
1915
    ;je    clear_next_entry
1916
 
1917
    mov   eax,[ebx+20-2]        ; first cluster of entry
1918
    mov   ax,[ebx+26]
1919
    and   eax,[fatMASK]
1920
 
1921
    test  byte [ebx+11],0x10    ; is it directory?
1922
    jz    clear_file            ; no
1923
 
1924
    push  eax ebx
1925
    mov   eax,edi
1926
    mov   ebx,deltree_buffer    ; save buffer over recursive call
1927
    call  hd_write              ; write directory sector to disk
74 mario79 1928
    cmp   [hd_error],0
1929
    jne   clear_error
1930
 
1 ha 1931
    pop   ebx eax
1932
 
1933
    call  clear_directory       ; recursive call !!!
1934
    jc    clear_error           ; exit if error found
1935
 
1936
    push  eax ebx
1937
    mov   eax,edi
1938
    mov   ebx,deltree_buffer
1939
    call  hd_read               ; read directory sector again
74 mario79 1940
    cmp  [hd_error],0
1941
    jne   clear_error_1
1942
 
1 ha 1943
    pop   ebx eax
1944
 
1945
  clear_file:
1946
    call  clear_cluster_chain
74 mario79 1947
    cmp  [hd_error],0
1948
    jne   clear_error
1 ha 1949
 
1950
  clear_long_filename:
1951
    mov   byte [ebx],0xe5
1952
 
1953
  clear_next_entry:
1954
    add   ebx,32                ; position of next dir entry
1955
    dec   edx
1956
    jnz   clear_analyze
1957
 
1958
    mov   eax,edi
1959
    mov   ebx,deltree_buffer
1960
    call  hd_write              ; write directory sector to disk
74 mario79 1961
    cmp   [hd_error],0
1962
    jne   clear_error
1 ha 1963
 
1964
    inc   eax                   ; next sector
1965
    dec   ecx
1966
    jnz   clear_new_sector
1967
 
1968
    mov   eax,esi
1969
    call  get_FAT               ; get next cluster
74 mario79 1970
    cmp   [hd_error],0
1971
    jne   clear_error
1972
 
1 ha 1973
    jmp   clear_new_cluster     ; clear it
1974
 
1975
  clear_write_last:
1976
    mov   eax,edi
1977
    mov   ebx,deltree_buffer
1978
    call  hd_write              ; write directory sector to disk
74 mario79 1979
    cmp   [hd_error],0
1980
    jne   clear_error
1 ha 1981
 
1982
  clear_end:
1983
    popad
1984
    clc
1985
    ret
74 mario79 1986
clear_error_1:
1987
    add  esp,8
1 ha 1988
  clear_error:
1989
    popad
1990
    stc
1991
    ret
1992
 
1993
 
1994
delete_entry_name:
1995
;-----------------------------------------------------
1996
; input  : eax = directory sector
1997
;          ebx = directory pointer in buffer
1998
;          longname_sec = 2 previous directory sectors
1999
; output : ecx = first cluster
2000
; change : eax,ebx,edx
2001
;-----------------------------------------------------
2002
    mov   byte [ebx],0xe5
2003
    mov   ecx,[ebx+20-2]        ; first cluster of file
2004
    mov   cx,[ebx+26]           ; 0 length files start cluster = 0
2005
    and   ecx,[fatMASK]
2006
 
2007
  delete_empty:
2008
    sub   ebx,32
2009
    cmp   ebx,buffer
2010
    jnb   delete_test_long
2011
 
2012
    mov   ebx,buffer
2013
    call  hd_write              ; write directory sector back
74 mario79 2014
    cmp   [hd_error],0
2015
    jne   delete_name_end
2016
 
1 ha 2017
    xor   eax,eax
2018
    xchg  eax,[longname_sec2]
2019
    xchg  eax,[longname_sec1]
2020
    test  eax,eax               ; is there previous directory sector?
2021
    jz    delete_name_end       ; no
2022
 
2023
    mov   ebx,buffer
2024
    call  hd_read               ; read previous sector
74 mario79 2025
    cmp  [hd_error],0
2026
    jne  delete_name_end
2027
 
1 ha 2028
    mov   ebx,buffer+0x1e0      ; start from last entry
2029
 
2030
  delete_test_long:
2031
    mov   dh,[ebx+11]           ; file attribute
2032
    and   dh,0xf
2033
    cmp   dh,0xf
2034
    jne   delete_write_buffer
2035
 
2036
    cmp   byte [ebx],0x40       ; end of long dir entry?
2037
    mov   byte [ebx],0xe5
2038
    jb    delete_empty
2039
 
2040
  delete_write_buffer:
2041
    mov   ebx,buffer
2042
    call  hd_write              ; write directory sector back
2043
 
2044
  delete_name_end:
2045
    ret
2046
 
2047
 
2048
rename:
2049
;-----------------------------------------------------------
2050
; input  : eax = source directory name
2051
;          edx = source path
2052
;          ebx = dest directory name
2053
;          edi = dest path
2054
; output : eax = 0 - ok
2055
;                3 - unknown FS
2056
;                5 - file not found
2057
;                8 - disk full
2058
;               10 - access denied
2059
;-----------------------------------------------------------
2060
    cmp   [fat_type],0
2061
    jnz   fat_ok_for_rename
2062
    mov   eax,ERROR_UNKNOWN_FS
2063
    ret
2064
 
2065
  fat_ok_for_rename:
2066
;    call  reserve_hd1
2067
 
2068
    pushad
2069
 
2070
    mov   ebx,edx               ; source path
2071
    call  get_cluster_of_a_path
2072
    jc    rename_entry_not_found
2073
 
2074
    mov   ebx,PUSHAD_EAX        ; source directory name
2075
    call  analyze_directory
2076
    jc    rename_entry_not_found
2077
 
2078
    mov   [sector_tmp],eax      ; save source sector
2079
    mov   [entry_pos],ebx
2080
    mov   esi,ebx
2081
    mov   edi,dir_entry
2082
    mov   ecx,32/4
2083
    cld
2084
    rep   movsd                 ; save entry
2085
 
2086
    mov   ebx,PUSHAD_EDI        ; dest path
2087
    call  get_cluster_of_a_path
2088
    jc    rename_entry_not_found
2089
 
2090
    mov   edx,eax               ; save dest directory cluster
2091
    mov   ebx,PUSHAD_EBX        ; dest directory name
2092
    push  [longname_sec1]
2093
    push  [longname_sec2]
2094
    call  analyze_directory     ; check if entry already exist
74 mario79 2095
    cmp  [hd_error],0
2096
    jne  rename_entry_already_exist_1
2097
 
1 ha 2098
    pop   [longname_sec2]
2099
    pop   [longname_sec1]
2100
    jnc   rename_entry_already_exist
2101
 
2102
    mov   eax,edx
2103
    call  analyze_directory_to_write
2104
    jc    rename_disk_full
2105
 
2106
    mov   esi,dir_entry
2107
    mov   edi,ebx
2108
    mov   ecx,32/4
2109
    cld
2110
    rep   movsd                 ; copy entry
2111
    mov   esi,PUSHAD_EBX        ; dest directory name
2112
    mov   edi,ebx
2113
    mov   ecx,11
2114
    rep   movsb                 ; copy name
2115
 
2116
    mov   ebx,buffer            ; save the directory name,length,cluster
2117
    call  hd_write
2118
 
2119
    test  byte [dir_entry+11],0x10 ; is it directory?
2120
    jz    rename_not_dir           ; no
2121
    mov   eax,[dir_entry+20-2]     ; FAT entry
2122
    mov   ax,[dir_entry+26]
2123
    and   eax,[fatMASK]
2124
    call  change_2dot_cluster
74 mario79 2125
    cmp   [hd_error],0
2126
    jne   rename_entry_already_exist
1 ha 2127
 
2128
  rename_not_dir:
74 mario79 2129
    cmp   [hd_error],0
2130
    jne   rename_entry_already_exist
1 ha 2131
    mov   eax,[sector_tmp]
2132
    mov   ebx,buffer
2133
    call  hd_read               ; read source directory sector
74 mario79 2134
    cmp  [hd_error],0
2135
    jne  rename_entry_already_exist
1 ha 2136
 
2137
    mov   ebx,[entry_pos]
2138
    call  delete_entry_name
74 mario79 2139
    cmp   [hd_error],0
2140
    jne   rename_entry_already_exist
1 ha 2141
 
2142
    popad
2143
    call  update_disk           ; write all of cache and fat to hd
74 mario79 2144
    cmp   [hd_error],0
2145
    jne   rename_entry_already_exist_2
1 ha 2146
    mov   [hd1_status],0
2147
    xor   eax,eax
2148
    ret
2149
 
2150
  rename_entry_not_found:
74 mario79 2151
    cmp  [hd_error],0
2152
    jne  rename_entry_already_exist
1 ha 2153
    popad
2154
    mov   [hd1_status],0
2155
    mov   eax,ERROR_FILE_NOT_FOUND
2156
    ret
2157
 
74 mario79 2158
  rename_entry_already_exist_1:
2159
    add   esp,8
1 ha 2160
  rename_entry_already_exist:
2161
    popad
74 mario79 2162
  rename_entry_already_exist_2:
1 ha 2163
    mov   [hd1_status],0
2164
    mov   eax,ERROR_ACCESS_DENIED
2165
    ret
2166
 
2167
  rename_disk_full:
74 mario79 2168
    cmp  [hd_error],0
2169
    jne  rename_entry_already_exist
1 ha 2170
    popad
2171
    mov   [hd1_status],0
2172
    mov   eax,ERROR_DISK_FULL
2173
    ret
2174
 
2175
 
2176
change_2dot_cluster:
2177
;-----------------------------------------------------------
2178
; input  : eax = directory cluster
2179
;          edx = value to save
2180
; change : eax,ebx,edx
2181
;-----------------------------------------------------------
2182
    cmp   eax,[LAST_CLUSTER]
2183
    ja    not_2dot              ; too big cluster number, something is wrong
2184
    sub   eax,2
2185
    jb    not_2dot
2186
 
2187
    imul  eax,[SECTORS_PER_CLUSTER]
2188
    add   eax,[DATA_START]
2189
    mov   ebx,buffer
2190
    call  hd_read
74 mario79 2191
    cmp  [hd_error],0
2192
    jne  not_2dot
1 ha 2193
 
2194
    cmp   dword [ebx+32],'..  '
2195
    jnz   not_2dot
2196
 
2197
    cmp   edx,[ROOT_CLUSTER]    ; is rootdir cluster?
2198
    jne   not_2dot_root
2199
    xor   edx,edx               ; yes. set it zero
2200
 
2201
  not_2dot_root:
2202
    mov   [ebx+32+26],dx        ; 16 bits low of cluster
2203
    shr   edx,16
2204
    mov   [ebx+32+20],dx        ; 16 bits high of cluster (=0 fat16)
2205
    call  hd_write
2206
 
2207
  not_2dot:
2208
    ret
2209
 
2210
 
2211
get_hd_info:
2212
;-----------------------------------------------------------
2213
; output : eax = 0 - ok
2214
;                3 - unknown FS
74 mario79 2215
;               10 - access denied
1 ha 2216
;          edx = cluster size in bytes
2217
;          ebx = total clusters on disk
2218
;          ecx = free clusters on disk
2219
;-----------------------------------------------------------
2220
    cmp   [fat_type],0
2221
    jnz   info_fat_ok
2222
    xor   edx,edx
2223
    xor   ebx,ebx
2224
    xor   ecx,ecx
2225
    mov   eax,ERROR_UNKNOWN_FS
2226
    ret
2227
 
2228
  info_fat_ok:
2229
;    call  reserve_hd1
2230
 
2231
    xor   ecx,ecx               ; count of free clusters
2232
    mov   eax,2
2233
    mov   ebx,[LAST_CLUSTER]
2234
 
2235
  info_cluster:
2236
    push  eax
2237
    call  get_FAT               ; get cluster info
74 mario79 2238
    cmp   [hd_error],0
2239
    jne   info_access_denied
2240
 
1 ha 2241
    test  eax,eax               ; is it free?
2242
    jnz   info_used             ; no
2243
    inc   ecx
2244
 
2245
  info_used:
2246
    pop   eax
2247
    inc   eax
2248
    cmp   eax,ebx               ; is above last cluster?
2249
    jbe   info_cluster          ; no. test next cluster
2250
 
2251
    dec   ebx                   ; cluster count
2252
    imul  edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
2253
    mov   [hd1_status],0
2254
    xor   eax,eax
2255
    ret
2256
 
74 mario79 2257
  info_access_denied:
2258
    add   esp,4
2259
    xor   edx,edx
2260
    xor   ebx,ebx
2261
    xor   ecx,ecx
2262
    mov   eax,ERROR_ACCESS_DENIED
2263
    ret
1 ha 2264
 
2265
update_disk:
2266
;-----------------------------------------------------------
2267
; write changed fat and cache to disk
2268
;-----------------------------------------------------------
2269
    cmp   [fat_change],0        ; is fat changed?
2270
    je    upd_no_change
2271
 
2272
    call  write_fat_sector
74 mario79 2273
    cmp   [hd_error],0
2274
    jne   update_disk_acces_denied
1 ha 2275
 
2276
  upd_no_change:
2277
 
2278
    call  write_cache
74 mario79 2279
  update_disk_acces_denied:
1 ha 2280
    ret
2281
 
2282
 
2283
;**************************************************************************
2284
;
2285
;   0x600008  - first entry in cache list
2286
;
2287
;            +0   - lba sector
2288
;            +4   - state of cache sector
2289
;                   0 = empty
2290
;                   1 = used for read  ( same as in hd )
2291
;                   2 = used for write ( differs from hd )
2292
;
2293
;      +65536 - cache entries
2294
;
2295
;**************************************************************************
2296
 
2297
 
2298
hd_read:
2299
;-----------------------------------------------------------
2300
; input  : eax = block to read
2301
;          ebx = destination
2302
;-----------------------------------------------------------
2303
    push  ecx esi edi           ; scan cache
2304
 
2305
    mov   ecx,cache_max         ; entries in cache
2306
    mov   esi,0x600000+8
2307
    mov   edi,1
2308
 
2309
  hdreadcache:
2310
 
2311
    cmp   dword [esi+4],0       ; empty
2312
    je    nohdcache
2313
 
2314
    cmp   [esi],eax             ; correct sector
2315
    je    yeshdcache
2316
 
2317
  nohdcache:
2318
 
2319
    add   esi,8
2320
    inc   edi
2321
    dec   ecx
2322
    jnz   hdreadcache
2323
 
2324
    call  find_empty_slot       ; ret in edi
74 mario79 2325
    cmp   [hd_error],0
2326
    jne   return_01
1 ha 2327
 
2328
    push  eax edx
2329
 
74 mario79 2330
    call  wait_for_hd_idle
2331
    cmp   [hd_error],0
2332
    jne   hd_read_error
2333
 
1 ha 2334
    cli
2335
    xor   eax,eax
2336
    mov   edx,[hdbase]
2337
    inc   edx
86 diamond 2338
    out   dx,al   ; ATAFeatures ॣ¨áâà "®á®¡¥­­®á⥩"
1 ha 2339
    inc   edx
2340
    inc   eax
86 diamond 2341
    out   dx,al   ; ATASectorCount áç¥â稪 ᥪâ®à®¢
1 ha 2342
    inc   edx
2343
    mov   eax,[esp+4]
86 diamond 2344
    out   dx,al   ; ATASectorNumber ॣ¨áâà ­®¬¥à  ᥪâ®à 
1 ha 2345
    shr   eax,8
2346
    inc   edx
86 diamond 2347
    out   dx,al   ; ATACylinder ­®¬¥à 樫¨­¤à  (¬« ¤è¨© ¡ ©â)
1 ha 2348
    shr   eax,8
2349
    inc   edx
86 diamond 2350
    out   dx,al   ; ­®¬¥à 樫¨­¤à  (áâ à訩 ¡ ©â)
1 ha 2351
    shr   eax,8
2352
    inc   edx
2353
    and   al,1+2+4+8
2354
    add   al,byte [hdid]
2355
    add   al,128+64+32
86 diamond 2356
    out   dx,al   ; ­®¬¥à £®«®¢ª¨/­®¬¥à ¤¨áª 
1 ha 2357
    inc   edx
2358
    mov   al,20h
86 diamond 2359
    out   dx,al   ; ATACommand ॣ¨áâà ª®¬ ­¤
1 ha 2360
    sti
2361
 
2362
    call  wait_for_sector_buffer
2363
 
2364
    cmp   [hd_error],0
2365
    jne   hd_read_error
2366
 
2367
    cli
2368
    push  edi
2369
    shl   edi,9
2370
    add   edi,0x600000+65536
2371
    mov   ecx,256
2372
    mov   edx,[hdbase]
2373
    cld
2374
    rep   insw
2375
    pop   edi
2376
    sti
2377
 
2378
    pop   edx eax
2379
 blok_read_2:
2380
    lea   esi,[edi*8+0x600000]
2381
    mov   [esi],eax             ; sector number
2382
    mov   dword [esi+4],1       ; hd read - mark as same as in hd
2383
 
2384
  yeshdcache:
2385
 
2386
    mov   esi,edi
2387
    shl   esi,9
2388
    add   esi,0x600000+65536
2389
    mov   edi,ebx
2390
    mov   ecx,512/4
2391
    cld
2392
    rep   movsd                 ; move data
74 mario79 2393
 return_01:
1 ha 2394
    pop   edi esi ecx
2395
    ret
2396
 
2397
 
2398
hd_write:
2399
;-----------------------------------------------------------
2400
; input  : eax = block
2401
;          ebx = pointer to memory
2402
;-----------------------------------------------------------
2403
    push  ecx esi edi
2404
 
2405
    ; check if the cache already has the sector and overwrite it
2406
 
2407
    mov   ecx,cache_max
2408
    mov   esi,0x600000+8
2409
    mov   edi,1
2410
 
2411
  hdwritecache:
2412
 
2413
    cmp   dword [esi+4],0       ; if cache slot is empty
2414
    je    not_in_cache_write
2415
 
2416
    cmp   [esi],eax             ; if the slot has the sector
2417
    je    yes_in_cache_write
2418
 
2419
  not_in_cache_write:
2420
 
2421
    add   esi,8
2422
    inc   edi
2423
    dec   ecx
2424
    jnz   hdwritecache
2425
 
2426
    ; sector not found in cache
2427
    ; write the block to a new location
2428
 
2429
    call  find_empty_slot       ; ret in edi
74 mario79 2430
    cmp   [hd_error],0
2431
    jne   hd_write_access_denied
1 ha 2432
 
2433
    lea   esi,[edi*8+0x600000]
2434
    mov   [esi],eax             ; sector number
2435
 
2436
  yes_in_cache_write:
2437
 
2438
    mov   dword [esi+4],2       ; write - differs from hd
2439
 
2440
    shl   edi,9
2441
    add   edi,0x600000+65536
2442
    mov   esi,ebx
2443
    mov   ecx,512/4
2444
    cld
2445
    rep   movsd                 ; move data
74 mario79 2446
 hd_write_access_denied:
1 ha 2447
    pop   edi esi ecx
2448
    ret
2449
 
2450
 
2451
write_cache:
2452
;-----------------------------------------------------------
2453
; write all changed sectors to disk
2454
;-----------------------------------------------------------
2455
    push  eax ecx edx esi edi
2456
 
2457
    ; write difference ( 2 ) from cache to hd
2458
 
2459
    mov   ecx,cache_max
2460
    mov   esi,0x600000+8
2461
    mov   edi,1
2462
 
2463
  write_cache_more:
2464
 
2465
    cmp   dword [esi+4],2       ; if cache slot is not different
2466
    jne   does_not_need_writing
2467
 
2468
    mov   dword [esi+4],1       ; same as in hd
2469
    mov   eax,[esi]             ; eax = sector to write
2470
 
2471
    cmp   eax,[PARTITION_START]
2472
    jb    danger
2473
    cmp   eax,[PARTITION_END]
2474
    ja    danger
2475
 
2476
    call  wait_for_hd_idle
74 mario79 2477
    cmp   [hd_error],0
2478
    jne   hd_write_error
1 ha 2479
 
2480
    cli
2481
    xor   eax,eax
2482
    mov   edx,[hdbase]
2483
    inc   edx
2484
    out   dx,al
2485
    inc   edx
2486
    inc   eax
2487
    out   dx,al
2488
    inc   edx
2489
    mov   eax,[esi]             ; eax = sector to write
2490
    out   dx,al
2491
    shr   eax,8
2492
    inc   edx
2493
    out   dx,al
2494
    shr   eax,8
2495
    inc   edx
2496
    out   dx,al
2497
    shr   eax,8
2498
    inc   edx
2499
    and   al,1+2+4+8
2500
    add   al,byte [hdid]
2501
    add   al,128+64+32
2502
    out   dx,al
2503
    inc   edx
2504
    mov   al,30h
2505
    out   dx,al
2506
    sti
2507
 
2508
    call  wait_for_sector_buffer
2509
 
2510
    cmp   [hd_error],0
2511
    jne   hd_write_error
2512
 
2513
    push  ecx esi
2514
 
2515
    cli
2516
    mov   esi,edi
2517
    shl   esi,9
2518
    add   esi,0x600000+65536    ; esi = from memory position
2519
    mov   ecx,256
2520
    mov   edx,[hdbase]
2521
    cld
2522
    rep   outsw
2523
    sti
2524
 
2525
    pop   esi ecx
2526
 
2527
  danger:
2528
  does_not_need_writing:
2529
 
2530
    add   esi,8
2531
    inc   edi
2532
    dec   ecx
2533
    jnz   write_cache_more
74 mario79 2534
 return_02:
1 ha 2535
    pop   edi esi edx ecx eax
2536
    ret
2537
 
2538
 
2539
find_empty_slot:
2540
;-----------------------------------------------------------
2541
; find empty or read slot, flush cache if next 10% is used by write
2542
; output : edi = cache slot
2543
;-----------------------------------------------------------
2544
    push  ecx esi
2545
 
2546
  search_again:
2547
 
2548
    mov   ecx,cache_max*10/100
2549
    mov   edi,[cache_search_start]
2550
 
2551
  search_for_empty:
2552
 
2553
    inc   edi
2554
    cmp   edi,cache_max
2555
    jbe   inside_cache
2556
    mov   edi,1
2557
 
2558
  inside_cache:
2559
 
2560
    cmp   dword [edi*8+0x600000+4],2    ; get cache slot info
2561
    jb    found_slot                    ; it's empty or read
2562
    dec   ecx
2563
    jnz   search_for_empty
2564
 
2565
    call  write_cache                   ; no empty slots found, write all
74 mario79 2566
    cmp   [hd_error],0
2567
    jne   found_slot_access_denied
2568
 
1 ha 2569
    jmp   search_again                  ; and start again
2570
 
2571
  found_slot:
2572
 
2573
    mov   [cache_search_start],edi
74 mario79 2574
  found_slot_access_denied:
1 ha 2575
    pop   esi ecx
2576
    ret
2577
 
2578
 
2579
save_hd_wait_timeout:
2580
 
2581
    push  eax
2582
    mov   eax,[timer_ticks];[0xfdf0]
2583
    add   eax,300               ; 3 sec timeout
2584
    mov   [hd_wait_timeout],eax
2585
    pop   eax
2586
    ret
2587
 
2588
 
2589
check_hd_wait_timeout:
2590
 
2591
    push  eax
2592
    mov   eax,[hd_wait_timeout]
2593
    cmp   [timer_ticks], eax ;[0xfdf0],eax
2594
    jg    hd_timeout_error
2595
    pop   eax
74 mario79 2596
    mov   [hd_error],0
1 ha 2597
    ret
2598
 
2599
iglobal
2600
  hd_timeout_str   db 'K : FS - HD timeout',13,10,0
2601
  hd_read_str      db 'K : FS - HD read error',13,10,0
2602
  hd_write_str     db 'K : FS - HD write error',13,10,0
74 mario79 2603
  hd_lba_str       db 'K : FS - HD LBA error',13,10,0
1 ha 2604
endg
2605
 
2606
hd_timeout_error:
2607
 
2608
    call  clear_hd_cache
2609
    call  clear_application_table_status
2610
    mov   esi,hd_timeout_str
2611
    call  sys_msg_board_str
74 mario79 2612
;    jmp   $
2613
    mov   [hd_error],1
2614
    pop   eax
2615
    ret
1 ha 2616
 
2617
hd_read_error:
2618
 
2619
    call  clear_hd_cache
2620
    call  clear_application_table_status
2621
    mov   esi,hd_read_str
2622
    call  sys_msg_board_str
74 mario79 2623
    pop   edx eax
2624
    jmp    return_01
2625
;    jmp   $
1 ha 2626
 
2627
hd_write_error:
2628
 
2629
    call  clear_hd_cache
2630
    call  clear_application_table_status
2631
    mov   esi,hd_write_str
2632
    call  sys_msg_board_str
74 mario79 2633
    jmp    return_02
2634
;    jmp   $
1 ha 2635
 
74 mario79 2636
hd_lba_error:
2637
    call  clear_hd_cache
2638
    call  clear_application_table_status
2639
    mov   esi,hd_lba_str
2640
    call  sys_msg_board_str
2641
    jmp   LBA_read_ret
1 ha 2642
 
2643
 
2644
wait_for_hd_idle:
2645
 
2646
    push  eax edx
2647
 
2648
    call  save_hd_wait_timeout
2649
 
2650
    mov   edx,[hdbase]
2651
    add   edx,0x7
2652
 
2653
  wfhil1:
2654
 
2655
    call  check_hd_wait_timeout
74 mario79 2656
    cmp   [hd_error],0
2657
    jne   @f
1 ha 2658
 
2659
    in    al,dx
2660
    test  al,128
2661
    jnz   wfhil1
74 mario79 2662
 
2663
 @@:
1 ha 2664
 
2665
    pop   edx eax
2666
    ret
2667
 
2668
 
74 mario79 2669
 
1 ha 2670
wait_for_sector_buffer:
2671
 
2672
    push  eax edx
2673
 
2674
    mov   edx,[hdbase]
2675
    add   edx,0x7
2676
 
2677
    call  save_hd_wait_timeout
2678
 
2679
  hdwait_sbuf:                  ; wait for sector buffer to be ready
2680
 
2681
    call  check_hd_wait_timeout
74 mario79 2682
    cmp   [hd_error],0
2683
    jne   @f
1 ha 2684
 
2685
    in    al,dx
2686
    test  al,8
2687
    jz    hdwait_sbuf
2688
 
2689
    mov   [hd_error],0
2690
 
2691
    cmp   [hd_setup],1          ; do not mark error for setup request
2692
    je    buf_wait_ok
2693
 
2694
    test  al,1                  ; previous command ended up with an error
2695
    jz    buf_wait_ok
74 mario79 2696
 @@:
1 ha 2697
    mov   [hd_error],1
2698
 
2699
  buf_wait_ok:
2700
 
2701
    pop   edx eax
2702
    ret
2703
 
2704
 
2705
 
2706
read_hd_file:
2707
;-----------------------------------------------------------------
2708
;
2709
; Converting old reading function for hd-application start.
2710
;
2711
; IN:
2712
;
2713
; eax - pointer to file (0 = read only first sector of drive: eg 'label')
2714
; ebx - file lenght
2715
; ecx - start 512 byte block number
2716
; edx - number of blocks to read
2717
; esi - pointer to return/work area (atleast 20 000 bytes)
2718
;
2719
; For new read function
2720
;
2721
; EAX   (PAR0)      pointer to file-name
2722
; ECX   (PAR1)      pointer to buffer
2723
; EBX   (PAR2)   vt file blocks to read
2724
; EDX   (PAR3)      pointer to path
2725
; ESI            vt first 512 block to read
2726
; EDI               if 0 - return root
2727
;--------------------------------------------------------------------------
2728
 
2729
    push  ecx esi edi
2730
    mov   esi,eax
2731
    mov   edi,startpath
2732
    mov   ecx,250
2733
    cld
2734
    rep   movsb
2735
    pop   edi esi ecx
2736
 
2737
    mov   eax,startpath
2738
    mov   [eax+ebx-12],byte 0
2739
 
2740
    push  eax ebx ecx edx esi
2741
 
2742
    pop   ecx ; pointer to buffer
2743
    add   ecx,1024
2744
    pop   ebx ; number of blocks to read
2745
    pop   esi ; first block to read
2746
    dec   esi
2747
    pop   eax ; file length
2748
    pop   edx ; pointer to path
2749
 
2750
    mov   edi,12
2751
    lea   eax,[eax+edx-12+1]
2752
    call  file_read
2753
 
2754
    ret
2755
 
71 diamond 2756
; \begin{diamond}
2757
hd_find_lfn:
2758
; in: esi->name
2759
; out: CF=1 - file not found
86 diamond 2760
;      else CF=0 and edi->direntry, eax=sector
83 diamond 2761
; destroys eax
2762
        push    esi edi
2763
        push    0
2764
        push    0
2765
        push    fat16_root_first
2766
        push    fat16_root_next
2767
        mov     eax, [ROOT_CLUSTER]
2768
        cmp     [fat_type], 32
2769
        jz      .fat32
2770
.loop:
2771
        call    fat_find_lfn
2772
        jc      .notfound
2773
        cmp     byte [esi], 0
2774
        jz      .found
2775
        test    byte [edi+11], 10h
2776
        jz      .notfound
2777
        and     dword [esp+12], 0
88 diamond 2778
        mov     eax, [edi+20-2]
2779
        mov     ax, [edi+26]    ; cluster
83 diamond 2780
.fat32:
2781
        mov     [esp+8], eax
2782
        mov     dword [esp+4], fat_notroot_first
2783
        mov     dword [esp], fat_notroot_next
2784
        jmp     .loop
71 diamond 2785
.notfound:
83 diamond 2786
        add     esp, 16
2787
        pop     edi esi
2788
        stc
2789
        ret
71 diamond 2790
.found:
86 diamond 2791
        lea     eax, [esp+8]
2792
        cmp     dword [eax], 0
2793
        jz      .root
2794
        call    fat_get_sector
2795
        jmp     .cmn
2796
.root:
2797
        mov     eax, [eax+4]
2798
        add     eax, [ROOT_START]
2799
.cmn:
83 diamond 2800
        add     esp, 20         ; CF=0
2801
        pop     esi
2802
        ret
74 mario79 2803
 
71 diamond 2804
;----------------------------------------------------------------
2805
;
2806
;  fs_HdRead - LFN variant for reading hard disk
2807
;
2808
;  esi  points to filename
2809
;  ebx  pointer to 64-bit number = first wanted byte, 0+
2810
;       may be ebx=0 - start from first byte
2811
;  ecx  number of bytes to read, 0+
2812
;  edx  mem location to return data
2813
;
77 diamond 2814
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 2815
;      eax = 0 ok read or other = errormsg
2816
;
2817
;--------------------------------------------------------------
2818
fs_HdRead:
74 mario79 2819
    cmp    [fat_type], 0
2820
    jnz    @f
2821
    or    ebx, -1
2822
    mov    eax, ERROR_UNKNOWN_FS
2823
    ret
71 diamond 2824
@@:
74 mario79 2825
    push    edi
2826
    cmp    byte [esi], 0
2827
    jnz    @f
71 diamond 2828
.noaccess:
74 mario79 2829
    pop    edi
2830
.noaccess_2:
2831
    or    ebx, -1
2832
    mov    eax, ERROR_ACCESS_DENIED
2833
    ret
2834
 
2835
.noaccess_3:
2836
    add esp,4
2837
.noaccess_1:
2838
    add esp,4
2839
.noaccess_4:
2840
    add esp,4*5
2841
    jmp  .noaccess_2
2842
 
71 diamond 2843
@@:
74 mario79 2844
    call    hd_find_lfn
2845
    jnc    .found
2846
    pop    edi
2847
    cmp   [hd_error],0
2848
    jne   .noaccess_2
2849
    or    ebx, -1
2850
    mov    eax, ERROR_FILE_NOT_FOUND
2851
    ret
2852
 
71 diamond 2853
.found:
74 mario79 2854
    test    byte [edi+11], 0x10    ; do not allow read directories
2855
    jnz    .noaccess
2856
    test    ebx, ebx
2857
    jz    .l1
2858
    cmp    dword [ebx+4], 0
2859
    jz    @f
77 diamond 2860
        xor     ebx, ebx
71 diamond 2861
.reteof:
74 mario79 2862
    mov    eax, 6
2863
    pop    edi
2864
    ret
71 diamond 2865
@@:
74 mario79 2866
    mov    ebx, [ebx]
71 diamond 2867
.l1:
77 diamond 2868
        push    ecx edx
2869
        push    0
2870
        mov     eax, [edi+28]
2871
        sub     eax, ebx
2872
        jb      .eof
2873
        cmp     eax, ecx
2874
        jae     @f
2875
        mov     ecx, eax
2876
        mov     byte [esp], 6
2877
@@:
74 mario79 2878
    mov    eax, [edi+20-2]
2879
    mov    ax, [edi+26]
71 diamond 2880
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
2881
.new_cluster:
74 mario79 2882
    jecxz    .new_sector
2883
    test    eax, eax
2884
    jz    .eof
2885
    cmp    eax, [fatRESERVED]
2886
    jae    .eof
2887
    mov    [cluster_tmp], eax
2888
    dec    eax
2889
    dec    eax
2890
    mov    edi, [SECTORS_PER_CLUSTER]
2891
    imul    eax, edi
2892
    add    eax, [DATA_START]
71 diamond 2893
.new_sector:
74 mario79 2894
    test    ecx, ecx
2895
    jz    .done
2896
    sub    ebx, 512
2897
    jae    .skip
2898
    add    ebx, 512
2899
    jnz    .force_buf
2900
    cmp    ecx, 512
2901
    jb    .force_buf
71 diamond 2902
; we may read directly to given buffer
74 mario79 2903
    push    ebx
2904
    mov    ebx, edx
2905
    call    hd_read
2906
    cmp  [hd_error],0
2907
    jne  .noaccess_1
2908
    pop    ebx
2909
    add    edx, 512
2910
    sub    ecx, 512
2911
    jmp    .skip
71 diamond 2912
.force_buf:
2913
; we must read sector to temporary buffer and then copy it to destination
74 mario79 2914
    push    eax ebx
2915
    mov    ebx, buffer
2916
    call    hd_read
2917
    cmp  [hd_error],0
2918
    jne  .noaccess_3
2919
 
2920
    mov    eax, ebx
2921
    pop    ebx
2922
    add    eax, ebx
2923
    push    ecx
2924
    add    ecx, ebx
2925
    cmp    ecx, 512
2926
    jbe    @f
2927
    mov    ecx, 512
71 diamond 2928
@@:
74 mario79 2929
    sub    ecx, ebx
2930
    mov    ebx, edx
2931
    call    memmove
2932
    add    edx, ecx
2933
    sub    [esp], ecx
2934
    pop    ecx
2935
    pop    eax
2936
    xor    ebx, ebx
71 diamond 2937
.skip:
74 mario79 2938
    inc    eax
2939
    dec    edi
2940
    jnz    .new_sector
2941
    mov    eax, [cluster_tmp]
2942
    call    get_FAT
2943
    cmp   [hd_error],0
2944
    jne   .noaccess_4
2945
 
2946
    jmp    .new_cluster
71 diamond 2947
.done:
77 diamond 2948
        mov     ebx, edx
2949
        pop     eax edx ecx edi
2950
        sub     ebx, edx
2951
        ret
71 diamond 2952
.eof:
77 diamond 2953
        mov     ebx, edx
2954
        pop     eax edx ecx
2955
        sub     ebx, edx
2956
        jmp     .reteof
75 diamond 2957
 
2958
;----------------------------------------------------------------
2959
;
2960
;  fs_HdReadFolder - LFN variant for reading hard disk folder
2961
;
2962
;  esi  points to filename
78 diamond 2963
;  ebx  pointer to structure 32-bit number = first wanted block, 0+
2964
;                          & flags (bitfields)
2965
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 2966
;  ecx  number of blocks to read, 0+
2967
;  edx  mem location to return data
2968
;
77 diamond 2969
;  ret ebx = blocks read or 0xffffffff folder not found
75 diamond 2970
;      eax = 0 ok read or other = errormsg
2971
;
2972
;--------------------------------------------------------------
2973
fs_HdReadFolder:
2974
        mov     eax, [ROOT_CLUSTER]
2975
        push    edi
2976
        cmp     byte [esi], 0
2977
        jz      .doit
2978
        call    hd_find_lfn
2979
        jnc     .found
2980
        pop     edi
2981
        or      ebx, -1
2982
        mov     eax, ERROR_FILE_NOT_FOUND
2983
        ret
2984
.found:
2985
        test    byte [edi+11], 0x10     ; do not allow read files
2986
        jnz     .found_dir
2987
        pop     edi
2988
        or      ebx, -1
2989
        mov     eax, ERROR_ACCESS_DENIED
2990
        ret
2991
.found_dir:
2992
        mov     eax, [edi+20-2]
2993
        mov     ax, [edi+26]    ; eax=cluster
2994
.doit:
2995
        push    esi ecx
2996
        push    ebp
2997
        sub     esp, 262*2      ; reserve space for LFN
2998
        mov     ebp, esp
78 diamond 2999
        push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE name
3000
        mov     ebx, [ebx]
75 diamond 3001
; init header
3002
        push    eax ecx
3003
        mov     edi, edx
3004
        mov     ecx, 32/4
3005
        xor     eax, eax
3006
        rep     stosd
3007
        pop     ecx eax
3008
        mov     byte [edx], 1   ; version
3009
        mov     esi, edi        ; esi points to BDFE
3010
.new_cluster:
3011
        mov     [cluster_tmp], eax
3012
        test    eax, eax
3013
        jnz     @f
3014
        cmp     [fat_type], 32
3015
        jz      .notfound
3016
        mov     eax, [ROOT_START]
3017
        push    [ROOT_SECTORS]
3018
        push    ebx
3019
        jmp     .new_sector
3020
@@:
3021
        dec     eax
3022
        dec     eax
3023
        imul    eax, [SECTORS_PER_CLUSTER]
3024
        push    [SECTORS_PER_CLUSTER]
3025
        add     eax, [DATA_START]
3026
        push    ebx
3027
.new_sector:
3028
        mov     ebx, buffer
3029
        mov     edi, ebx
3030
        call    hd_read
3031
        cmp     [hd_error], 0
3032
        jnz     .notfound2
3033
        add     ebx, 512
3034
        push    eax
3035
.l1:
3036
        call    fat_get_name
3037
        jc      .l2
3038
        cmp     byte [edi+11], 0xF
3039
        jnz     .do_bdfe
3040
        add     edi, 0x20
3041
        cmp     edi, ebx
3042
        jb      .do_bdfe
3043
        pop     eax
3044
        inc     eax
3045
        dec     dword [esp+4]
3046
        jnz     @f
3047
        mov     eax, [cluster_tmp]
3048
        test    eax, eax
3049
        jz      .done
3050
        call    get_FAT
3051
        cmp     [hd_error], 0
3052
        jnz     .notfound2
3053
        cmp     eax, 2
3054
        jb      .done
3055
        cmp     eax, [fatRESERVED]
3056
        jae     .done
3057
        push    eax
3058
        mov     eax, [SECTORS_PER_CLUSTER]
3059
        mov     [esp+8], eax
3060
        pop     eax
3061
        mov     [cluster_tmp], eax
3062
        dec     eax
3063
        dec     eax
3064
        imul    eax, [SECTORS_PER_CLUSTER]
3065
        add     eax, [DATA_START]
3066
@@:
3067
        mov     ebx, buffer
3068
        mov     edi, ebx
3069
        call    hd_read
3070
        cmp     [hd_error], 0
3071
        jnz     .notfound2
3072
        add     ebx, 512
3073
        push    eax
3074
.do_bdfe:
3075
        inc     dword [edx+8]   ; new file found
3076
        dec     dword [esp+4]
3077
        jns     .l2
3078
        dec     ecx
3079
        js      .l2
3080
        inc     dword [edx+4]   ; new file block copied
3081
        call    fat_entry_to_bdfe
3082
.l2:
3083
        add     edi, 0x20
3084
        cmp     edi, ebx
3085
        jb      .l1
3086
        pop     eax
3087
        inc     eax
3088
        dec     dword [esp+4]
3089
        jnz     .new_sector
3090
        mov     eax, [cluster_tmp]
3091
        test    eax, eax
3092
        jz      .done
3093
        call    get_FAT
3094
        cmp     [hd_error], 0
3095
        jnz     .notfound2
3096
        cmp     eax, 2
3097
        jb      .done
3098
        cmp     eax, [fatRESERVED]
3099
        jae     .done
3100
        push    eax
3101
        mov     eax, [SECTORS_PER_CLUSTER]
3102
        mov     [esp+8], eax
3103
        pop     eax
3104
        pop     ebx
3105
        add     esp, 4
3106
        jmp     .new_cluster
3107
.notfound2:
3108
        add     esp, 8
3109
.notfound:
3110
        add     esp, 262*2+4
3111
        pop     ebp ecx esi edi
3112
        mov     eax, ERROR_FILE_NOT_FOUND
3113
        or      ebx, -1
3114
        ret
3115
.done:
3116
        add     esp, 262*2+4+8
3117
        pop     ebp
77 diamond 3118
        mov     ebx, [edx+4]
75 diamond 3119
        xor     eax, eax
3120
        dec     ecx
3121
        js      @f
3122
        mov     al, ERROR_END_OF_FILE
3123
@@:
3124
        pop     ecx esi edi
3125
        ret
3126
 
83 diamond 3127
fat16_root_next:
3128
        cmp     edi, buffer+0x200-0x20
3129
        jae     fat16_root_next_sector
3130
        add     edi, 0x20
3131
        ret     ; CF=0
3132
fat16_root_next_sector:
3133
; read next sector
3134
        push    ecx
3135
        mov     ecx, [eax+4]
3136
        inc     ecx
3137
        mov     [eax+4], ecx
3138
        cmp     ecx, [ROOT_SECTORS]
3139
        pop     ecx
3140
        jae     fat16_root_first.readerr
3141
fat16_root_first:
3142
        mov     eax, [eax+4]
3143
        add     eax, [ROOT_START]
3144
        push    ebx
3145
        mov     edi, buffer
3146
        mov     ebx, edi
3147
        call    hd_read
3148
        pop     ebx
3149
        cmp     [hd_error], 0
3150
        jnz     .readerr
3151
        ret     ; CF=0
3152
.readerr:
3153
        stc
3154
        ret
3155
fat16_root_begin_write:
3156
        push    edi eax
3157
        call    fat16_root_first
3158
        pop     eax edi
3159
        ret
3160
fat16_root_end_write:
3161
        pusha
3162
        mov     eax, [eax+4]
3163
        add     eax, [ROOT_START]
3164
        mov     ebx, buffer
3165
        call    hd_write
3166
        popa
3167
        ret
3168
fat16_root_next_write:
3169
        cmp     edi, buffer+0x200
3170
        jae     @f
3171
        ret
3172
@@:
3173
        call    fat16_root_end_write
3174
        jmp     fat16_root_next_sector
3175
fat16_root_extend_dir:
3176
        stc
3177
        ret
3178
 
3179
fat_notroot_next:
3180
        cmp     edi, buffer+0x200-0x20
3181
        jae     fat_notroot_next_sector
3182
        add     edi, 0x20
3183
        ret     ; CF=0
3184
fat_notroot_next_sector:
3185
        push    ecx
3186
        mov     ecx, [eax+4]
3187
        inc     ecx
3188
        cmp     ecx, [SECTORS_PER_CLUSTER]
3189
        jae     fat_notroot_next_cluster
3190
        mov     [eax+4], ecx
3191
        jmp     @f
3192
fat_notroot_next_cluster:
3193
        push    eax
3194
        mov     eax, [eax]
3195
        call    get_FAT
3196
        mov     ecx, eax
3197
        pop     eax
3198
        cmp     [hd_error], 0
3199
        jnz     fat_notroot_next_err
3200
        cmp     ecx, [fatRESERVED]
3201
        jae     fat_notroot_next_err
3202
        mov     [eax], ecx
3203
        and     dword [eax+4], 0
3204
@@:
3205
        pop     ecx
3206
fat_notroot_first:
3207
        call    fat_get_sector
3208
        push    ebx
3209
        mov     edi, buffer
3210
        mov     ebx, edi
3211
        call    hd_read
3212
        pop     ebx
3213
        cmp     [hd_error], 0
3214
        jnz     @f
3215
        ret     ; CF=0
3216
fat_notroot_next_err:
3217
        pop     ecx
3218
@@:
3219
        stc
3220
        ret
3221
fat_notroot_begin_write:
3222
        push    eax edi
3223
        call    fat_notroot_first
3224
        pop     edi eax
3225
        ret
3226
fat_notroot_end_write:
3227
        call    fat_get_sector
3228
        push    ebx
3229
        mov     ebx, buffer
3230
        call    hd_write
3231
        pop     ebx
3232
        ret
3233
fat_notroot_next_write:
3234
        cmp     edi, buffer+0x200
3235
        jae     @f
3236
        ret
3237
@@:
3238
        push    eax
3239
        call    fat_notroot_end_write
3240
        pop     eax
3241
        jmp     fat_notroot_next_sector
3242
fat_notroot_extend_dir:
3243
        push    eax
3244
        mov     eax, [eax]
3245
        call    get_free_FAT
3246
        jnc     .found
3247
        pop     eax
3248
        ret     ; CF=1
3249
.found:
3250
        push    edx
3251
        mov     edx, [fatEND]
3252
        call    set_FAT
3253
        mov     edx, eax
3254
        mov     eax, [esp+4]
3255
        mov     eax, [eax]
3256
        push    edx
3257
        mov     [f_del], 1
3258
        call    set_FAT
3259
        pop     edx
3260
        cmp     [hd_error], 0
3261
        jz      @f
3262
        pop     edx
3263
        pop     eax
3264
        stc
3265
        ret
3266
@@:
3267
        push    ecx
3268
        or      ecx, -1
3269
        call    add_disk_free_space
3270
; zero new cluster
3271
        mov     ecx, 512/4
3272
        mov     edi, buffer
3273
        push    edi
3274
        xor     eax, eax
3275
        rep     stosd
3276
        pop     edi
3277
        pop     ecx
3278
        mov     eax, [esp+4]
3279
        mov     [eax], edx
3280
        and     dword [eax+4], 0
3281
        pop     edx
3282
        mov     eax, [eax]
3283
        dec     eax
3284
        dec     eax
3285
        push    ebx ecx
3286
        mov     ecx, [SECTORS_PER_CLUSTER]
3287
        imul    eax, ecx
3288
        add     eax, [DATA_START]
3289
        mov     ebx, edi
3290
@@:
3291
        call    hd_write
3292
        inc     eax
3293
        loop    @b
3294
        pop     ecx ebx eax
3295
        clc
3296
        ret
3297
 
3298
fat_get_sector:
3299
        push    ecx
3300
        mov     ecx, [eax]
3301
        dec     ecx
3302
        dec     ecx
3303
        imul    ecx, [SECTORS_PER_CLUSTER]
3304
        add     ecx, [DATA_START]
3305
        add     ecx, [eax+4]
3306
        mov     eax, ecx
3307
        pop     ecx
3308
        ret
3309
 
3310
;----------------------------------------------------------------
3311
;
3312
;  fs_HdRewrite - LFN variant for writing hard disk
3313
;
3314
;  esi  points to filename
3315
;  ebx  ignored (reserved)
3316
;  ecx  number of bytes to write, 0+
3317
;  edx  mem location to data
3318
;
3319
;  ret ebx = number of written bytes
3320
;      eax = 0 ok read or other = errormsg
3321
;
3322
;--------------------------------------------------------------
3323
fshrad:
3324
        mov     eax, ERROR_ACCESS_DENIED
3325
        xor     ebx, ebx
3326
        ret
3327
fshrfs:
3328
        mov     eax, ERROR_UNKNOWN_FS
3329
        xor     ebx, ebx
3330
        ret
3331
 
3332
fs_HdRewrite:
3333
        cmp     [fat_type], 0
3334
        jz      fshrfs
3335
        cmp     byte [esi], 0
3336
        jz      fshrad
3337
        pushad
3338
        xor     ebp, ebp
3339
        push    esi
3340
@@:
3341
        lodsb
3342
        test    al, al
3343
        jz      @f
3344
        cmp     al, '/'
3345
        jnz     @b
3346
        lea     ebp, [esi-1]
3347
        jmp     @b
3348
@@:
3349
        pop     esi
3350
        test    ebp, ebp
3351
        jnz     .noroot
3352
        mov     ebp, [ROOT_CLUSTER]
3353
        cmp     [fat_type], 32
3354
        jz      .pushnotroot
3355
        push    fat16_root_extend_dir
3356
        push    fat16_root_end_write
3357
        push    fat16_root_next_write
3358
        push    fat16_root_begin_write
3359
        xor     ebp, ebp
3360
        push    ebp
3361
        push    ebp
3362
        push    fat16_root_first
3363
        push    fat16_root_next
3364
        jmp     .common1
3365
.noroot:
3366
; check existence
3367
        mov     byte [ebp], 0
3368
        call    hd_find_lfn
3369
        mov     byte [ebp], '/'
3370
        lea     esi, [ebp+1]
3371
        jnc     @f
3372
        mov     eax, ERROR_FILE_NOT_FOUND
3373
.ret1:
3374
        mov     [esp+28], eax
3375
        popad
3376
        xor     ebx, ebx
3377
        ret
3378
@@:
3379
        test    byte [edi+11], 0x10     ; must be directory
3380
        mov     eax, ERROR_ACCESS_DENIED
3381
        jz      .ret1
3382
        mov     ebp, [edi+20-2]
3383
        mov     bp, [edi+26]            ; ebp=cluster
3384
        mov     eax, ERROR_FAT_TABLE
3385
        cmp     ebp, 2
3386
        jb      .ret1
3387
.pushnotroot:
3388
        push    fat_notroot_extend_dir
3389
        push    fat_notroot_end_write
3390
        push    fat_notroot_next_write
3391
        push    fat_notroot_begin_write
3392
        push    0
3393
        push    ebp
3394
        push    fat_notroot_first
3395
        push    fat_notroot_next
3396
.common1:
3397
        call    fat_find_lfn
3398
        jc      .notfound
3399
; found, delete FAT chain
3400
        push    edi
3401
        xor     eax, eax
3402
        mov     dword [edi+28], eax     ; zero size
3403
        xor     ecx, ecx
3404
        mov     eax, [edi+20-2]
3405
        mov     ax, [edi+26]
3406
        mov     word [edi+20], cx
3407
        mov     word [edi+26], cx
3408
        test    eax, eax
3409
        jz      .done1
3410
        mov     [f_del], 1
3411
@@:
3412
        cmp     eax, [fatRESERVED]
3413
        jae     .done1
3414
        push    edx
3415
        xor     edx, edx
3416
        call    set_FAT
3417
        mov     eax, edx
3418
        pop     edx
3419
        inc     ecx
3420
        jmp     @b
3421
.done1:
3422
        pop     edi
3423
        call    get_time_for_file
3424
        mov     [edi+22], ax
3425
        call    get_date_for_file
3426
        mov     [edi+24], ax
3427
        mov     [edi+18], ax
3428
        or      byte [edi+11], 20h      ; set 'archive' attribute
3429
        jmp     .doit
3430
.notfound:
3431
; file is not found; generate short name
3432
        call    fat_name_is_legal
3433
        jc      @f
3434
        add     esp, 32
3435
        popad
3436
        mov     eax, ERROR_FILE_NOT_FOUND
3437
        xor     ebx, ebx
3438
        ret
3439
@@:
3440
        sub     esp, 12
3441
        mov     edi, esp
3442
        call    fat_gen_short_name
3443
.test_short_name_loop:
3444
        push    esi edi ecx
3445
        mov     esi, edi
3446
        lea     eax, [esp+12+12+8]
3447
        mov     [eax], ebp
3448
        and     dword [eax+4], 0
3449
        call    dword [eax-4]
3450
        jc      .found
3451
.test_short_name_entry:
3452
        cmp     byte [edi+11], 0xF
3453
        jz      .test_short_name_cont
3454
        mov     ecx, 11
3455
        push    esi edi
3456
        repz    cmpsb
3457
        pop     edi esi
3458
        jz      .short_name_found
3459
.test_short_name_cont:
3460
        lea     eax, [esp+12+12+8]
3461
        call    dword [eax-8]
3462
        jnc     .test_short_name_entry
3463
        jmp     .found
3464
.short_name_found:
3465
        pop     ecx edi esi
3466
        call    fat_next_short_name
3467
        jnc     .test_short_name_loop
3468
.disk_full:
3469
        add     esp, 12+32
3470
        popa
3471
        mov     eax, ERROR_DISK_FULL
3472
        xor     ebx, ebx
3473
        ret
3474
.found:
3475
        pop     ecx edi esi
3476
; now find space in directory
3477
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
3478
        mov     al, '~'
3479
        push    ecx edi
3480
        mov     ecx, 8
3481
        repnz   scasb
3482
        push    1
3483
        pop     eax     ; 1 entry
3484
        jnz     .notilde
3485
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
3486
        xor     eax, eax
3487
@@:
3488
        cmp     byte [esi], 0
3489
        jz      @f
3490
        inc     esi
3491
        inc     eax
3492
        jmp     @b
3493
@@:
3494
        sub     esi, eax
3495
        add     eax, 12+13
3496
        mov     ecx, 13
3497
        push    edx
3498
        cdq
3499
        div     ecx
3500
        pop     edx
3501
.notilde:
3502
        push    -1
3503
        push    -1
3504
        push    -1
3505
; find  successive entries in directory
3506
        xor     ecx, ecx
3507
        push    eax
3508
        lea     eax, [esp+16+8+12+8]
3509
        mov     [eax], ebp
3510
        and     dword [eax+4], 0
3511
        call    dword [eax-4]
3512
        pop     eax
3513
        jnc     .scan_dir
3514
.fsfrfe3:
3515
        add     esp, 12+8+12+32
3516
        popad
3517
        mov     eax, 11
3518
        xor     ebx, ebx
3519
        ret
3520
.scan_dir:
3521
        cmp     byte [edi], 0
3522
        jz      .free
3523
        cmp     byte [edi], 0xE5
3524
        jz      .free
3525
        xor     ecx, ecx
3526
.scan_cont:
3527
        push    eax
3528
        lea     eax, [esp+16+8+12+8]
3529
        call    dword [eax-8]
3530
        pop     eax
3531
        jnc     .scan_dir
3532
        cmp     [hd_error], 0
3533
        jnz     .fsfrfe3
3534
        push    eax
3535
        lea     eax, [esp+16+8+12+8]
3536
        call    dword [eax+20]          ; extend directory
3537
        pop     eax
3538
        jnc     .scan_dir
3539
        add     esp, 12+8+12+32
3540
        popad
3541
        mov     eax, ERROR_DISK_FULL
3542
        xor     ebx, ebx
3543
        ret
3544
.free:
3545
        test    ecx, ecx
3546
        jnz     @f
3547
        mov     [esp], edi
3548
        mov     ecx, [esp+12+8+12+8]
3549
        mov     [esp+4], ecx
3550
        mov     ecx, [esp+12+8+12+12]
3551
        mov     [esp+8], ecx
3552
        xor     ecx, ecx
3553
@@:
3554
        inc     ecx
3555
        cmp     ecx, eax
3556
        jb      .scan_cont
3557
; found!
3558
; calculate name checksum
3559
        push    esi ecx
3560
        mov     esi, [esp+8+12]
3561
        mov     ecx, 11
3562
        xor     eax, eax
3563
@@:
3564
        ror     al, 1
3565
        add     al, [esi]
3566
        inc     esi
3567
        loop    @b
3568
        pop     ecx esi
3569
        pop     edi
3570
        pop     dword [esp+8+12+12]
3571
        pop     dword [esp+8+12+12]
3572
; edi points to first entry in free chunk
3573
        dec     ecx
3574
        jz      .nolfn
3575
        push    esi
3576
        push    eax
3577
        lea     eax, [esp+8+8+12+8]
3578
        call    dword [eax+8]         ; begin write
3579
        mov     al, 40h
3580
.writelfn:
3581
        or      al, cl
3582
        mov     esi, [esp+4]
3583
        push    ecx
3584
        dec     ecx
3585
        imul    ecx, 13
3586
        add     esi, ecx
3587
        stosb
3588
        mov     cl, 5
3589
        call    fs_RamdiskRewrite.read_symbols
3590
        mov     ax, 0xF
3591
        stosw
3592
        mov     al, [esp+4]
3593
        stosb
3594
        mov     cl, 6
3595
        call    fs_RamdiskRewrite.read_symbols
3596
        xor     eax, eax
3597
        stosw
3598
        mov     cl, 2
3599
        call    fs_RamdiskRewrite.read_symbols
3600
        pop     ecx
3601
        lea     eax, [esp+8+8+12+8]
3602
        call    dword [eax+12]         ; next write
3603
        xor     eax, eax
3604
        loop    .writelfn
3605
        pop     eax
3606
        pop     esi
3607
;        lea     eax, [esp+8+12+8]
3608
;        call    dword [eax+16]          ; end write
3609
.nolfn:
3610
        xchg    esi, [esp]
3611
        mov     ecx, 11
3612
        rep     movsb
3613
        mov     word [edi], 20h         ; attributes
3614
        sub     edi, 11
3615
        pop     esi ecx
3616
        add     esp, 12
3617
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
3618
        call    get_time_for_file
3619
        mov     [edi+14], ax            ; creation time
3620
        mov     [edi+22], ax            ; last write time
3621
        call    get_date_for_file
3622
        mov     [edi+16], ax            ; creation date
3623
        mov     [edi+24], ax            ; last write date
3624
        mov     [edi+18], ax            ; last access date
3625
        xor     ecx, ecx
3626
        mov     word [edi+20], cx       ; high word of cluster
3627
        mov     word [edi+26], cx       ; low word of cluster - to be filled
3628
        mov     dword [edi+28], ecx     ; file size - to be filled
3629
.doit:
3630
        lea     eax, [esp+8]
3631
        call    dword [eax+16]  ; flush directory
3632
        push    ecx
3633
        mov     ecx, [esp+4+32+24]
3634
        push    ecx
3635
        push    edi
3636
        mov     esi, edx
3637
        test    ecx, ecx
3638
        jz      .done
3639
        mov     eax, 2
3640
        call    get_free_FAT
3641
        jc      .diskfull
3642
        push    eax
3643
        mov     [edi+26], ax
3644
        shr     eax, 16
3645
        mov     [edi+20], ax
3646
        lea     eax, [esp+16+8]
3647
        call    dword [eax+16]  ; flush directory
3648
        pop     eax
3649
        push    edx
3650
        mov     edx, [fatEND]
3651
        call    set_FAT
3652
        pop     edx
3653
.write_cluster:
3654
        push    eax
3655
        dec     eax
3656
        dec     eax
3657
        mov     ebp, [SECTORS_PER_CLUSTER]
3658
        imul    eax, ebp
3659
        add     eax, [DATA_START]
3660
; write data
3661
.write_sector:
3662
        mov     ecx, 512
3663
        cmp     dword [esp+8], ecx
3664
        jb      .writeshort
3665
; we can write directly from given buffer
3666
        mov     ebx, esi
3667
        add     esi, ecx
3668
        jmp     .writecommon
3669
.writeshort:
3670
        mov     ecx, [esp+8]
3671
        push    ecx
3672
        mov     edi, buffer
3673
        mov     ebx, edi
3674
        rep     movsb
3675
        mov     ecx, buffer+0x200
3676
        sub     ecx, edi
3677
        push    eax
3678
        xor     eax, eax
3679
        rep     stosb
3680
        pop     eax
3681
        pop     ecx
3682
.writecommon:
3683
        call    hd_write
3684
        cmp     [hd_error], 0
3685
        jnz     .writeerr
3686
        inc     eax
3687
        sub     dword [esp+8], ecx
3688
        jz      .writedone
3689
        dec     ebp
3690
        jnz     .write_sector
3691
; allocate new cluster
3692
        pop     eax
3693
        mov     ecx, eax
3694
        call    get_free_FAT
3695
        jc      .diskfull
3696
        mov     [f_del], 1
3697
        push    edx
3698
        mov     edx, [fatEND]
3699
        call    set_FAT
3700
        xchg    eax, ecx
3701
        mov     edx, ecx
3702
        call    set_FAT
3703
        pop     edx
3704
        xchg    eax, ecx
3705
        jmp     .write_cluster
3706
.diskfull:
3707
        mov     eax, ERROR_DISK_FULL
3708
        jmp     .ret
3709
.writeerr:
3710
        pop     eax
3711
        sub     esi, ecx
3712
        mov     eax, 11
3713
        jmp     .ret
3714
.writedone:
3715
        pop     eax
3716
.done:
3717
        xor     eax, eax
3718
.ret:
3719
        pop     edi ecx
3720
        mov     ebx, esi
3721
        sub     ebx, edx
3722
        pop     ebp
3723
        mov     [esp+32+28], eax
3724
        lea     eax, [esp+8]
3725
        call    dword [eax+8]
3726
        mov     [edi+28], ebx
3727
        call    dword [eax+16]
3728
        mov     [esp+32+16], ebx
3729
        lea     eax, [ebx+511]
3730
        shr     eax, 9
3731
        mov     ecx, [SECTORS_PER_CLUSTER]
3732
        lea     eax, [eax+ecx-1]
3733
        xor     edx, edx
3734
        div     ecx
3735
        mov     ecx, ebp
3736
        sub     ecx, eax
3737
        call    add_disk_free_space
3738
        add     esp, 32
3739
        call    update_disk
3740
        popad
3741
        ret
3742
 
86 diamond 3743
fs_HdGetFileInfo:
3744
        cmp     [fat_type], 0
3745
        jnz     @f
3746
        mov     eax, ERROR_UNKNOWN_FS
3747
        ret
3748
@@:
3749
        cmp     byte [esi], 0
3750
        jnz     @f
3751
        mov     eax, 2
3752
        ret
3753
@@:
3754
        push    edi
3755
        call    hd_find_lfn
3756
        pushfd
3757
        cmp     [hd_error], 0
3758
        jz      @f
3759
        popfd
3760
        pop     edi
3761
        mov     eax, 11
3762
        ret
3763
@@:
3764
        popfd
3765
        jmp     fs_GetFileInfo_finish
3766
 
3767
fs_HdSetFileInfo:
3768
        cmp     [fat_type], 0
3769
        jnz     @f
3770
        mov     eax, ERROR_UNKNOWN_FS
3771
        ret
3772
@@:
3773
        cmp     byte [esi], 0
3774
        jnz     @f
3775
        mov     eax, 2
3776
        ret
3777
@@:
3778
        push    edi
3779
        call    hd_find_lfn
3780
        pushfd
3781
        cmp     [hd_error], 0
3782
        jz      @f
3783
        popfd
3784
        pop     edi
3785
        mov     eax, 11
3786
        ret
3787
@@:
3788
        popfd
3789
        jnc     @f
3790
        pop     edi
3791
        mov     eax, ERROR_FILE_NOT_FOUND
3792
        ret
3793
@@:
3794
        push    eax
3795
        call    bdfe_to_fat_entry
3796
        pop     eax
3797
        mov     ebx, buffer
3798
        call    hd_write
3799
        call    update_disk
3800
        pop     edi
3801
        xor     eax, eax
3802
        ret
3803
 
74 mario79 3804
; \end{diamond}