Subversion Repositories Kolibri OS

Rev

Rev 83 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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