Subversion Repositories Kolibri OS

Rev

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

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