Subversion Repositories Kolibri OS

Rev

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