Subversion Repositories Kolibri OS

Rev

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