Subversion Repositories Kolibri OS

Rev

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