Subversion Repositories Kolibri OS

Rev

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