Subversion Repositories Kolibri OS

Rev

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

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