Subversion Repositories Kolibri OS

Rev

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