Subversion Repositories Kolibri OS

Rev

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