Subversion Repositories Kolibri OS

Rev

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