Subversion Repositories Kolibri OS

Rev

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