Subversion Repositories Kolibri OS

Rev

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