Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;;  FAT32.INC                                                      ;;
  4. ;;                                                                 ;;
  5. ;;  FAT16/32 functions for MenuetOS                                ;;
  6. ;;                                                                 ;;
  7. ;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
  8. ;;                                                                 ;;
  9. ;;  See file COPYING for details                                   ;;
  10. ;;                                                                 ;;
  11. ;;  23.04.2006 LFN read - diamond                                  ;;
  12. ;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
  13. ;;             to MBR, see file part_set.inc - Mario79             ;;
  14. ;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
  15. ;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
  16. ;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
  17. ;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
  18. ;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
  19. ;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
  20. ;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
  21. ;;  08.11.2004 rename - ATV                                        ;;
  22. ;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
  23. ;;  20.10.2004 Makedir/Removedir - ATV                             ;;
  24. ;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
  25. ;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
  26. ;;  24.5.2004  Write back buffer for File_write -VT                ;;
  27. ;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
  28. ;;  30.3.2004  Error parameters at function return - VT            ;;
  29. ;;  01.5.2002  Bugfix in device write - VT                         ;;
  30. ;;  20.5.2002  Hd status check - VT                                ;;
  31. ;;  29.6.2002  Improved fat32 verification - VT                    ;;
  32. ;;                                                                 ;;
  33. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  34.  
  35. cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
  36.  
  37. ERROR_SUCCESS        = 0
  38. ERROR_DISK_BASE      = 1
  39. ERROR_UNSUPPORTED_FS = 2
  40. ERROR_UNKNOWN_FS     = 3
  41. ERROR_PARTITION      = 4
  42. ERROR_FILE_NOT_FOUND = 5
  43. ERROR_END_OF_FILE    = 6
  44. ERROR_MEMORY_POINTER = 7
  45. ERROR_DISK_FULL      = 8
  46. ERROR_FAT_TABLE      = 9
  47. ERROR_ACCESS_DENIED  = 10
  48.  
  49. PUSHAD_EAX equ [esp+28]
  50. PUSHAD_ECX equ [esp+24]
  51. PUSHAD_EDX equ [esp+20]
  52. PUSHAD_EBX equ [esp+16]
  53. PUSHAD_EBP equ [esp+8]
  54. PUSHAD_ESI equ [esp+4]
  55. PUSHAD_EDI equ [esp+0]
  56.  
  57. cluster              dd 0       ; used by file_write,makedir,append
  58. partition_count      dd 0       ; partitions found by set_FAT32_variables
  59. longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
  60. longname_sec2        dd 0       ; directory sectors for delete long filename
  61.  
  62. hd_error             dd 0       ; set by wait_for_sector_buffer
  63. hd_setup             dd 0
  64. hd_wait_timeout      dd 0
  65.  
  66. cluster_tmp          dd 0       ; used by analyze_directory
  67.                                 ; and analyze_directory_to_write
  68.  
  69. file_size            dd 0       ; used by file_read
  70.  
  71. sector_tmp           dd 0       ; used by rename,append,file_write
  72. entry_pos            dd 0       ; used by rename,append,file_write
  73.  
  74. old_filesize         dd 0       ; used by append
  75. new_filepos          dd 0       ; used by append
  76. bytes2write          dd 0       ; used by append
  77.  
  78. cache_search_start   dd 0       ; used by find_empty_slot
  79.  
  80. fat_in_cache         dd -1
  81. fat_cache:           times 512 db 0
  82.  
  83. uglobal
  84.  Sector512:                      ; label for dev_hdcd.inc
  85.   buffer:              times 512 db 0
  86.   deltree_buffer:      times 512 db 0
  87. endg
  88.  
  89. iglobal
  90.   NewDirEntry1         db ".          ",0x10
  91.                      times 20 db 0
  92.   NewDirEntry2         db "..         ",0x10
  93.                      times 20 db 0
  94. endg
  95.  
  96. uglobal
  97.   dir_entry:           times 32 db 0
  98.  
  99.   startpath:           times 255 db 0
  100.  
  101.   fat16_root           db 0       ; flag for fat16 rootdir
  102.   f_del                db 0       ; 1=overwrite fat entry
  103.   fat_change           db 0       ; 1=fat has changed
  104.  
  105. endg
  106.  
  107. reserve_hd1:
  108.  
  109.     cli
  110.     cmp   [hd1_status],0
  111.     je    reserve_ok1
  112.  
  113.     sti
  114.     call  change_task
  115.     jmp   reserve_hd1
  116.  
  117.   reserve_ok1:
  118.  
  119.     push  eax
  120.     mov   eax,[0x3000]
  121.     shl   eax,5
  122.     mov   eax,[eax+0x3000+4]
  123.     mov   [hd1_status],eax
  124.     pop   eax
  125.     sti
  126.     ret
  127.  
  128.  
  129. clear_hd_cache:
  130.  
  131.     push  eax ecx edi
  132.     mov   edi,0x600000
  133.     mov   ecx,16384
  134.     xor   eax,eax
  135.     cld
  136.     rep   stosd                 ; clear hd cache with 0
  137.     mov   [cache_search_start],eax
  138.     mov   [fat_in_cache],-1
  139.     mov   [fat_change],0
  140.     pop   edi ecx eax
  141.     ret
  142.  
  143. problem_partition db 0  ; used for partitions search
  144.  
  145. include  'part_set.inc'
  146.  
  147. set_FAT:
  148. ;--------------------------------
  149. ; input  : EAX = cluster
  150. ;          EDX = value to save
  151. ; output : EDX = old value
  152. ;--------------------------------
  153.     push  eax ebx esi
  154.  
  155.     cmp   eax,2
  156.     jb    sfc_error
  157.     cmp   eax,[LAST_CLUSTER]
  158.     ja    sfc_error
  159.     cmp   [fat_type],16
  160.     je    sfc_1
  161.     add   eax,eax
  162.   sfc_1:
  163.     add   eax,eax
  164.     mov   esi,511
  165.     and   esi,eax               ; esi = position in fat sector
  166.     shr   eax,9                 ; eax = fat sector
  167.     add   eax,[FAT_START]
  168.     mov   ebx,fat_cache
  169.  
  170.     cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
  171.     je    sfc_in_cache          ; yes
  172.  
  173.     cmp   [fat_change],0        ; is fat changed?
  174.     je    sfc_no_change         ; no
  175.     call  write_fat_sector      ; yes. write it into disk
  176.  
  177.   sfc_no_change:
  178.     mov   [fat_in_cache],eax    ; save fat sector
  179.     call  hd_read
  180.  
  181.   sfc_in_cache:
  182.     cmp   [fat_type],16
  183.     jne   sfc_test32
  184.  
  185.     cmp   [f_del],1             ; overwrite previous value?
  186.     je    sfc_set16             ; yes
  187.     cmp   word [ebx+esi],0      ; is cluster free?
  188.     je    sfc_set16             ; yes
  189.     mov   dword [8*0x100000],0xffffff
  190.     mov   edx,[ebx+esi]         ; get old value
  191.     jmp   sfc_nonzero
  192.  
  193.   sfc_set16:
  194.     xchg  [ebx+esi],dx          ; save new value and get old value
  195.     jmp   sfc_write
  196.  
  197.   sfc_test32:
  198.     mov   eax,[fatMASK]
  199.     cmp   [f_del],1             ; overwrite previous value?
  200.     je    sfc_set32             ; yes
  201.     test  eax,[ebx+esi]         ; is cluster free?
  202.     je    sfc_set32             ; yes
  203.     mov   dword [8*0x100000],0xffffff
  204.     mov   edx,[ebx+esi]         ; get old value
  205.     jmp   sfc_nonzero
  206.  
  207.   sfc_set32:
  208.     and   edx,eax
  209.     xor   eax,-1                ; mask for high bits
  210.     and   eax,[ebx+esi]         ; get high 4 bits
  211.     or    eax,edx
  212.     mov   edx,[ebx+esi]         ; get old value
  213.     mov   [ebx+esi],eax         ; save new value
  214.  
  215.   sfc_write:
  216.     mov   [fat_change],1        ; fat has changed
  217.  
  218.   sfc_nonzero:
  219.     and   edx,[fatMASK]
  220.  
  221.   sfc_error:
  222.     pop   esi ebx eax
  223.     ret
  224.  
  225.  
  226. get_FAT:
  227. ;--------------------------------
  228. ; input  : EAX = cluster
  229. ; output : EAX = next cluster
  230. ;--------------------------------
  231.     push  ebx esi
  232.  
  233.     cmp   [fat_type],16
  234.     je    gfc_1
  235.     add   eax,eax
  236.   gfc_1:
  237.     add   eax,eax
  238.     mov   esi,511
  239.     and   esi,eax               ; esi = position in fat sector
  240.     shr   eax,9                 ; eax = fat sector
  241.     add   eax,[FAT_START]
  242.     mov   ebx,fat_cache
  243.  
  244.     cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
  245.     je    gfc_in_cache
  246.  
  247.     cmp   [fat_change],0        ; is fat changed?
  248.     je    gfc_no_change         ; no
  249.     call  write_fat_sector      ; yes. write it into disk
  250.  
  251.   gfc_no_change:
  252.     mov   [fat_in_cache],eax
  253.     call  hd_read
  254.  
  255.   gfc_in_cache:
  256.     mov   eax,[ebx+esi]
  257.     and   eax,[fatMASK]
  258.     pop   esi ebx
  259.     ret
  260.  
  261.  
  262. get_free_FAT:
  263. ;-----------------------------------------------------------
  264. ; input  : EAX = # cluster for start the searching
  265. ; output : if CARRY=0 EAX = # first cluster found free
  266. ;          if CARRY=1 disk full
  267. ; Note   : for more speed need to use fat_cache directly
  268. ;-----------------------------------------------------------
  269.     push  ecx
  270.     mov   ecx,[LAST_CLUSTER]    ; counter for full disk
  271.     sub   ecx,2
  272.  
  273.   gff_test:
  274.     cmp   eax,[LAST_CLUSTER]    ; if above last cluster start at cluster 2
  275.     jbe   gff_in_range
  276.     mov   eax,2
  277.  
  278.   gff_in_range:
  279.     push  eax
  280.     call  get_FAT               ; get cluster state
  281.     test  eax,eax               ; is it free?
  282.     pop   eax
  283.     je    gff_found             ; yes
  284.     inc   eax                   ; next cluster
  285.     dec   ecx                   ; is all checked?
  286.     jns   gff_test              ; no
  287.  
  288.   gff_not_found:
  289.     pop   ecx                   ; yes. disk is full
  290.     stc
  291.     ret
  292.  
  293.   gff_found:
  294.     pop   ecx
  295.     clc
  296.     ret
  297.  
  298.  
  299. write_fat_sector:
  300. ;-----------------------------------------------------------
  301. ; write changed fat to disk
  302. ;-----------------------------------------------------------
  303.     push  eax ebx ecx
  304.  
  305.     mov   [fat_change],0
  306.     mov   eax,[fat_in_cache]
  307.     cmp   eax,-1
  308.     jz    write_fat_not_used
  309.     mov   ebx,fat_cache
  310.     mov   ecx,[NUMBER_OF_FATS]
  311.  
  312.   write_next_fat:
  313.     call  hd_write
  314.     add   eax,[SECTORS_PER_FAT]
  315.     dec   ecx
  316.     jnz   write_next_fat
  317.  
  318.   write_fat_not_used:
  319.     pop   ecx ebx eax
  320.     ret
  321.  
  322.  
  323. analyze_directory:
  324. ;-----------------------------------------------------------
  325. ; input  : EAX = first cluster of the directory
  326. ;          EBX = pointer to filename
  327. ; output : IF CARRY=0 EAX = sector where th file is found
  328. ;                     EBX = pointer in buffer
  329. ;                     [buffer .. buffer+511]
  330. ;                     ECX,EDX,ESI,EDI not changed
  331. ;          IF CARRY=1 filename not found
  332. ; Note   : if cluster=0 it's changed to read rootdir
  333. ;          save 2 previous directory sectors in longname_sec
  334. ;-----------------------------------------------------------
  335.     push  ecx edx esi edi ebx   ; ebx = [esp+0]
  336.     mov   [longname_sec1],0
  337.     mov   [longname_sec2],0
  338.  
  339.   adr_new_cluster:
  340.     mov   [cluster_tmp],eax
  341.     mov   [fat16_root],0
  342.     cmp   eax,[LAST_CLUSTER]
  343.     ja    adr_not_found         ; too big cluster number, something is wrong
  344.     cmp   eax,2
  345.     jnb   adr_data_cluster
  346.  
  347.     mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
  348.     cmp   [fat_type],16
  349.     jne   adr_data_cluster
  350.     mov   eax,[ROOT_START]
  351.     mov   edx,[ROOT_SECTORS]
  352.     mov   [fat16_root],1        ; flag for fat16 rootdir
  353.     jmp   adr_new_sector
  354.  
  355.   adr_data_cluster:
  356.     sub   eax,2
  357.     mov   edx,[SECTORS_PER_CLUSTER]
  358.     imul  eax,edx
  359.     add   eax,[DATA_START]
  360.  
  361.   adr_new_sector:
  362.     mov   ebx,buffer
  363.     call  hd_read
  364.     mov   ecx,512/32            ; count of dir entrys per sector = 16
  365.  
  366.   adr_analyze:
  367.     mov   edi,[ebx+11]          ; file attribute
  368.     and   edi,0xf
  369.     cmp   edi,0xf
  370.     je    adr_long_filename
  371.     test  edi,0x8               ; skip over volume label
  372.     jne   adr_long_filename     ; Note: label can be same name as file/dir
  373.  
  374.     mov   esi,[esp+0]           ; filename need to be uppercase
  375.     mov   edi,ebx
  376.     push  ecx
  377.     mov   ecx,11
  378.     cld
  379.     rep   cmpsb                 ; compare 8+3 filename
  380.     pop   ecx
  381.     je    adr_found
  382.  
  383.   adr_long_filename:
  384.     add   ebx,32                ; position of next dir entry
  385.     dec   ecx
  386.     jnz   adr_analyze
  387.  
  388.     mov   ecx,[longname_sec1]   ; save 2 previous directory sectors
  389.     mov   [longname_sec1],eax   ; for delete long filename
  390.     mov   [longname_sec2],ecx
  391.     inc   eax                   ; next sector
  392.     dec   edx
  393.     jne   adr_new_sector
  394.     cmp   [fat16_root],1        ; end of fat16 rootdir
  395.     je    adr_not_found
  396.  
  397.   adr_next_cluster:
  398.     mov   eax,[cluster_tmp]
  399.     call  get_FAT               ; get next cluster
  400.     cmp   eax,2                 ; incorrect fat chain?
  401.     jb    adr_not_found         ; yes
  402.     cmp   eax,[fatRESERVED]     ; is it end of directory?
  403.     jb    adr_new_cluster       ; no. analyse it
  404.  
  405.   adr_not_found:
  406.     pop   edi edi esi edx ecx   ; first edi will remove ebx
  407.     stc                         ; file not found
  408.     ret
  409.  
  410.   adr_found:
  411.     pop   edi edi esi edx ecx   ; first edi will remove ebx
  412.     clc                         ; file found
  413.     ret
  414.  
  415.  
  416. analyze_directory_to_write:
  417. ;-----------------------------------------------------------
  418. ; input  : EAX = first cluster of the directory
  419. ; output : IF CARRY=0 EAX = sector where the empty pos is found
  420. ;                     EBX = pointer in buffer
  421. ;                     [buffer .. buffer+511]
  422. ;                     ECX,EDX,ESI,EDI not changed
  423. ;          IF CARRY=1 disk full or fat corrupted
  424. ; Note   : if cluster=0 it's changed to read rootdir
  425. ;-----------------------------------------------------------
  426.     push  ecx edx edi
  427.  
  428.   adw_new_cluster:
  429.     mov   [cluster_tmp],eax
  430.     mov   [fat16_root],0
  431.     cmp   eax,[LAST_CLUSTER]
  432.     ja    adw_not_found         ; too big cluster number, something is wrong
  433.     cmp   eax,2
  434.     jnb   adw_data_cluster
  435.  
  436.     mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
  437.     cmp   [fat_type],16
  438.     jne   adw_data_cluster
  439.     mov   eax,[ROOT_START]
  440.     mov   edx,[ROOT_SECTORS]
  441.     mov   [fat16_root],1        ; flag for fat16 rootdir
  442.     jmp   adw_new_sector
  443.  
  444.   adw_data_cluster:
  445.     sub   eax,2
  446.     mov   edx,[SECTORS_PER_CLUSTER]
  447.     imul  eax,edx
  448.     add   eax,[DATA_START]
  449.  
  450.   adw_new_sector:
  451.     mov   ebx,buffer
  452.     call  hd_read
  453.     mov   ecx,512/32            ; count of dir entrys per sector = 16
  454.  
  455.   adw_analyze:
  456.     cmp   byte [ebx],0x00       ; is free entry?
  457.     je    adw_found             ; yes
  458.     cmp   byte [ebx],0xe5       ; is deleted entry?
  459.     je    adw_found             ; yes
  460.     add   ebx,32                ; position of next dir entry
  461.     dec   ecx
  462.     jnz   adw_analyze
  463.  
  464.     inc   eax                   ; next sector
  465.     dec   edx
  466.     jne   adw_new_sector
  467.     cmp   [fat16_root],1        ; end of fat16 rootdir
  468.     je    adw_not_found
  469.  
  470.     mov   eax,[cluster_tmp]
  471.     call  get_FAT               ; get next cluster
  472.     cmp   eax,2                 ; incorrect fat chain?
  473.     jb    adw_not_found         ; yes
  474.     cmp   eax,[fatRESERVED]     ; is it end of directory?
  475.     jb    adw_new_cluster       ; no. analyse it
  476.  
  477.     mov   eax,2                 ; this block of code add a new cluster
  478.     call  get_free_FAT          ; for the directory because the directory
  479.     jc    adw_not_found         ; is full
  480.  
  481.     mov   edx,[fatEND]          ; new end for directory
  482.     call  set_FAT
  483.  
  484.     push  eax                   ; save new cluster
  485.     mov   edx,eax
  486.     mov   eax,[cluster_tmp]     ; change last cluster to point new cluster
  487.     mov   [f_del],1
  488.     call  set_FAT
  489.     mov   [f_del],0
  490.  
  491.     mov   ecx,-1                ; remove 1 cluster from free disk space
  492.     call  add_disk_free_space
  493.  
  494.     mov   ecx,512/4
  495.     xor   eax,eax
  496.     mov   edi,buffer
  497.     cld
  498.     rep   stosd                 ; clear new directory cluster
  499.     pop   eax
  500.  
  501.     sub   eax,2
  502.     mov   ecx,[SECTORS_PER_CLUSTER]
  503.     imul  eax,ecx
  504.     add   eax,[DATA_START]
  505.     mov   ebx,buffer
  506.     push  eax                   ; save sector number
  507.  
  508.   adw_set_empty_directory:
  509.     call  hd_write
  510.     inc   eax                   ; next sector
  511.     dec   ecx
  512.     jnz   adw_set_empty_directory
  513.  
  514.     pop   eax
  515.  
  516.   adw_found:
  517.     pop   edi edx ecx
  518.     clc                         ; free space found
  519.     ret
  520.  
  521.   adw_not_found:
  522.     pop   edi edx ecx
  523.     stc                         ; free space not found
  524.     ret
  525.  
  526.  
  527. get_data_cluster:
  528. ;-----------------------------------------------------------
  529. ; input  : EAX = cluster
  530. ;          EBX = pointer to buffer
  531. ;          EDX = # blocks to read in buffer
  532. ;          ESI = # blocks to skip over
  533. ; output : if CARRY=0 ok EBX/EDX/ESI updated
  534. ;          if CARRY=1 cluster out of range
  535. ; Note   : if cluster=0 it's changed to read rootdir
  536. ;-----------------------------------------------------------
  537.     push  eax ecx
  538.  
  539.     mov   [fat16_root],0
  540.     cmp   eax,[LAST_CLUSTER]
  541.     ja    gdc_error             ; too big cluster number, something is wrong
  542.     cmp   eax,2
  543.     jnb   gdc_cluster
  544.  
  545.     mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
  546.     cmp   [fat_type],16
  547.     jne   gdc_cluster
  548.     mov   eax,[ROOT_START]
  549.     mov   ecx,[ROOT_SECTORS]    ; Note: not cluster size
  550.     mov   [fat16_root],1        ; flag for fat16 rootdir
  551.     jmp   gdc_read
  552.  
  553.   gdc_cluster:
  554.     sub   eax,2
  555.     mov   ecx,[SECTORS_PER_CLUSTER]
  556.     imul  eax,ecx
  557.     add   eax,[DATA_START]
  558.  
  559.   gdc_read:
  560.     test  esi,esi               ; first wanted block
  561.     je    gdcl1                 ; yes, skip count is 0
  562.     dec   esi
  563.     jmp   gdcl2
  564.  
  565.   gdcl1:
  566.     call  hd_read
  567.     add   ebx,512               ; update pointer
  568.     dec   edx
  569.  
  570.   gdcl2:
  571.     test  edx,edx               ; is all read?
  572.     je    out_of_read
  573.  
  574.     inc   eax                   ; next sector
  575.     dec   ecx
  576.     jnz   gdc_read
  577.  
  578.   out_of_read:
  579.     pop   ecx eax
  580.     clc
  581.     ret
  582.  
  583.   gdc_error:
  584.     pop   ecx eax
  585.     stc
  586.     ret
  587.  
  588.  
  589. set_data_cluster:
  590. ;-----------------------------------------------------------
  591. ; input  : EAX = cluster
  592. ;          EBX = pointer to buffer
  593. ; output : if CARRY=0 ok
  594. ;          if CARRY=1 cluster out of range
  595. ;-----------------------------------------------------------
  596.     push  eax ebx edx
  597.  
  598.     cmp   eax,[LAST_CLUSTER]
  599.     ja    sdc_error             ; too big cluster number, something is wrong
  600.     sub   eax,2
  601.     jb    sdc_error             ; don't allow rootdir write
  602.  
  603.     mov   edx,[SECTORS_PER_CLUSTER]
  604.     imul  eax,edx
  605.     add   eax,[DATA_START]
  606.  
  607.   sdc_write:
  608.     call  hd_write
  609.     add   ebx,512               ; update pointer
  610.     inc   eax
  611.     dec   edx
  612.     jnz   sdc_write
  613.     pop   edx ebx eax
  614.     clc
  615.     ret
  616.  
  617.   sdc_error:
  618.     pop   edx ebx eax
  619.     stc
  620.     ret
  621.  
  622.  
  623. get_cluster_of_a_path:
  624. ;---------------------------------------------------------
  625. ; input  : EBX = pointer to a path string
  626. ;          (example: the path "/files/data/document" become
  627. ;                             "files......data.......document...0"
  628. ;          '.' = space char
  629. ;          '0' = char(0) (ASCII=0) !!! )
  630. ; output : if (CARRY=1) -> ERROR in the PATH
  631. ;          if (CARRY=0) -> EAX=cluster
  632. ;---------------------------------------------------------
  633.     push  ebx edx
  634.  
  635.     mov   eax,[ROOT_CLUSTER]
  636.     mov   edx,ebx
  637.  
  638. search_end_of_path:
  639.     cmp   byte [edx],0
  640.     je    found_end_of_path
  641.  
  642.     inc   edx ; '/'
  643.     mov   ebx,edx
  644.     call  analyze_directory
  645.     jc    directory_not_found
  646.  
  647.     mov   eax,[ebx+20-2]        ; read the HIGH 16bit cluster field
  648.     mov   ax,[ebx+26]           ; read the LOW 16bit cluster field
  649.     and   eax,[fatMASK]
  650.     add   edx,11                ; 8+3 (name+extension)
  651.     jmp   search_end_of_path
  652.  
  653. found_end_of_path:
  654.     pop   edx ebx
  655.     clc                         ; no errors
  656.     ret
  657.  
  658. directory_not_found:
  659.     pop   edx ebx
  660.     stc                         ; errors occour
  661.     ret
  662.  
  663.  
  664. bcd2bin:
  665. ;----------------------------------
  666. ; input  : AL=BCD number (eg. 0x11)
  667. ; output : AH=0
  668. ;          AL=decimal number (eg. 11)
  669. ;----------------------------------
  670.     xor   ah,ah
  671.     shl   ax,4
  672.     shr   al,4
  673.     aad
  674.     ret
  675.  
  676.  
  677. get_date_for_file:
  678. ;-----------------------------------------------------
  679. ; Get date from CMOS and pack day,month,year in AX
  680. ; DATE   bits  0..4   : day of month 0..31
  681. ;              5..8   : month of year 1..12
  682. ;              9..15  : count of years from 1980
  683. ;-----------------------------------------------------
  684.     mov   al,0x7        ;day
  685.     out   0x70,al
  686.     in    al,0x71
  687.     call  bcd2bin
  688.     ror   eax,5
  689.  
  690.     mov   al,0x8        ;month
  691.     out   0x70,al
  692.     in    al,0x71
  693.     call  bcd2bin
  694.     ror   eax,4
  695.  
  696.     mov   al,0x9        ;year
  697.     out   0x70,al
  698.     in    al,0x71
  699.     call  bcd2bin
  700.     add   ax,20         ;because CMOS return only the two last
  701.                         ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
  702.     rol   eax,9         ;need the difference with 1980 (eg. 2001-1980)
  703.     ret
  704.  
  705.  
  706. get_time_for_file:
  707. ;-----------------------------------------------------
  708. ; Get time from CMOS and pack hour,minute,second in AX
  709. ; TIME   bits  0..4   : second (the low bit is lost)
  710. ;              5..10  : minute 0..59
  711. ;              11..15 : hour 0..23
  712. ;-----------------------------------------------------
  713.     mov   al,0x0        ;second
  714.     out   0x70,al
  715.     in    al,0x71
  716.     call  bcd2bin
  717.     ror   eax,6
  718.  
  719.     mov   al,0x2        ;minute
  720.     out   0x70,al
  721.     in    al,0x71
  722.     call  bcd2bin
  723.     ror   eax,6
  724.  
  725.     mov   al,0x4        ;hour
  726.     out   0x70,al
  727.     in    al,0x71
  728.     call  bcd2bin
  729.     rol   eax,11
  730.     ret
  731.  
  732.  
  733. set_current_time_for_entry:
  734. ;-----------------------------------------------------
  735. ; Set current time/date for file entry
  736. ; input  : ebx = file entry pointer
  737. ;-----------------------------------------------------
  738.     push  eax
  739.     call  get_time_for_file     ; update files date/time
  740.     mov   [ebx+22],ax
  741.     call  get_date_for_file
  742.     mov   [ebx+24],ax
  743.     pop   eax
  744.     ret
  745.  
  746.  
  747. makedir:
  748. ;-----------------------------------------------------
  749. ; input  : eax = directory name
  750. ;          edx = path
  751. ; output : eax = 0 - ok
  752. ;                3 - unknown FS
  753. ;                5 - file not found
  754. ;                8 - disk full
  755. ;               10 - access denied
  756. ; Note   : can only make one directory at time
  757. ;-----------------------------------------------------
  758.     cmp   [fat_type],0
  759.     jnz   make_dir_fat_ok
  760.     mov   eax,ERROR_UNKNOWN_FS
  761.     ret
  762.  
  763.   make_dir_fat_ok:
  764. ;    call  reserve_hd1
  765.  
  766.     pushad
  767.  
  768.     mov   ebx,edx
  769.     call  get_cluster_of_a_path
  770.     jnc   make_dir_found_path
  771.  
  772.   make_dir_path_not_found:
  773.     popad
  774.     call  update_disk           ; write all of cache and fat to hd
  775.     mov   [hd1_status],0
  776.     mov   eax,ERROR_FILE_NOT_FOUND
  777.     ret
  778.  
  779.   make_dir_disk_full:
  780.     popad
  781.     call  update_disk           ; write all of cache and fat to hd
  782.     mov   [hd1_status],0
  783.     mov   eax,ERROR_DISK_FULL
  784.     ret
  785.  
  786.   make_dir_already_exist:
  787.     mov   eax,[cluster]         ; directory cluster
  788.     xor   edx,edx               ; free
  789.     mov   [f_del],1
  790.     call  set_FAT
  791.     mov   [f_del],0
  792.  
  793.     popad
  794.     call  update_disk           ; write all of cache and fat to hd
  795.     mov   [hd1_status],0
  796.     mov   eax,ERROR_ACCESS_DENIED
  797.     ret
  798.  
  799.   make_dir_found_path:
  800.     cmp   eax,[ROOT_CLUSTER]
  801.     jnz   make_dir_not_root
  802.     xor   eax,eax
  803.  
  804.   make_dir_not_root:
  805.     mov   ecx,eax               ; directorys start cluster
  806.     mov   word [NewDirEntry2+26],cx ; 16 bits low of cluster
  807.     shr   ecx,16
  808.     mov   word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16)
  809.  
  810.     push  eax                   ; save parent directory cluster
  811.     mov   eax,2
  812.     call  get_free_FAT
  813.     mov   [cluster],eax         ; first free cluster
  814.     pop   eax
  815.     jc    make_dir_disk_full
  816.  
  817.     push  eax
  818.     mov   eax,[cluster]         ; directory cluster
  819.     mov   edx,[fatEND]          ; end for directory
  820.     call  set_FAT
  821.     pop   eax
  822.  
  823.     mov   ebx,PUSHAD_EAX        ; dir name
  824.     push  eax
  825.     call  analyze_directory     ; check if directory already exist
  826.     pop   eax
  827.     jnc   make_dir_already_exist ; need to free allocated cluster!
  828.  
  829.     call  analyze_directory_to_write
  830.     jc    make_dir_already_exist ; need to free allocated cluster!
  831.  
  832.     mov   esi,PUSHAD_EAX        ; dir name
  833.     mov   edi,ebx               ; pointer in buffer
  834.     mov   ecx,11
  835.     cld
  836.     rep   movsb
  837.  
  838.     mov   dword [ebx+28],0      ; dir size is always 0
  839.     mov   ecx,[cluster]
  840.     mov   [ebx+26],cx           ; 16 bits low of cluster
  841.     mov   word [NewDirEntry1+26],cx
  842.     shr   ecx,16
  843.     mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
  844.     mov   word [NewDirEntry1+20],cx
  845.     mov   byte [ebx+11],0x10    ; attribute = directory
  846.  
  847.     call  set_current_time_for_entry
  848.     mov   ecx,[ebx+22]
  849.     mov   dword [NewDirEntry1+22],ecx
  850.     mov   dword [NewDirEntry2+22],ecx
  851.  
  852.     mov   ebx,buffer            ; save the directory name,length,cluster
  853.     call  hd_write
  854.  
  855.     mov   ecx,512/4
  856.     xor   eax,eax
  857.     mov   edi,buffer
  858.     cld
  859.     rep   stosd                 ; clear new directory cluster
  860.  
  861.     mov   eax,[cluster]         ; new directory cluster
  862.     sub   eax,2
  863.     mov   edx,[SECTORS_PER_CLUSTER]
  864.     imul  eax,edx
  865.     add   eax,[DATA_START]
  866.     mov   ebx,buffer
  867.     add   eax,edx               ; start from last sector
  868.  
  869.   dir_set_empty_directory:
  870.     dec   eax                   ; next sector
  871.     cmp   edx,1                 ; is first directory sector?
  872.     jnz   not_first_sector      ; no. write empty sector
  873.     mov   esi,NewDirEntry1
  874.     mov   edi,buffer
  875.     mov   ecx,64/4
  876.     cld
  877.     rep   movsd                 ; copy 2 first directory entrys "." and ".."
  878.  
  879.   not_first_sector:
  880.     call  hd_write
  881.     dec   edx
  882.     jnz   dir_set_empty_directory
  883.  
  884.     mov   ecx,-1                ; remove 1 cluster from free disk space
  885.     call  add_disk_free_space
  886.  
  887.     popad
  888.     call  update_disk           ; write all of cache and fat to hd
  889.     mov   [hd1_status],0
  890.     xor   eax,eax
  891.     ret
  892.  
  893.  
  894. removedir:
  895. ;-----------------------------------------------------
  896. ; input  : eax = file/directory name
  897. ;          edx = path
  898. ; output : eax = 0 - ok
  899. ;                3 - unknown FS
  900. ;                5 - file not found
  901. ;               10 - access denied
  902. ;-----------------------------------------------------
  903.     cmp   [fat_type],0
  904.     jnz   remove_dir_fat_ok
  905.     mov   eax,ERROR_UNKNOWN_FS
  906.     ret
  907.  
  908.   remove_dir_fat_ok:
  909. ;    call  reserve_hd1
  910.  
  911.     push  edi
  912.     mov   edi,1                 ; allow directory remove
  913.     call  file_delete
  914.     pop   edi
  915.  
  916.     call  update_disk           ; write all of cache and fat to hd
  917.     mov   [hd1_status],0
  918.     ret
  919.  
  920.  
  921. add_disk_free_space:
  922. ;-----------------------------------------------------
  923. ; input  : ecx = cluster count
  924. ; Note   : negative = remove clusters from free space
  925. ;          positive = add clusters to free space
  926. ;-----------------------------------------------------
  927.     test  ecx,ecx               ; no change
  928.     je    add_dfs_no
  929.     cmp   [fat_type],32         ; free disk space only used by fat32
  930.     jne   add_dfs_no
  931.  
  932.     push  eax ebx
  933.     mov   eax,[ADR_FSINFO]
  934.     mov   ebx,buffer
  935.     call  hd_read
  936.     cmp   dword [ebx+0x1fc],0xaa550000 ; check sector id
  937.     jne   add_not_fs
  938.  
  939.     add   [ebx+0x1e8],ecx
  940.     call  hd_write
  941.  
  942.   add_not_fs:
  943.     pop   ebx eax
  944.  
  945.   add_dfs_no:
  946.     ret
  947.  
  948.  
  949. file_append:
  950. ;-----------------------------------------------------
  951. ; input  : eax = file name
  952. ;          edx = path
  953. ;          ecx = pointer to buffer
  954. ;          ebx = bytes to write (0 = truncate file)
  955. ;          esi = start position (-1 = end of file)
  956. ; output : eax = 0 - ok
  957. ;                3 - unknown FS
  958. ;                5 - file not found
  959. ;                6 - end of file
  960. ;                8 - disk full
  961. ;                9 - fat table corrupted
  962. ;               10 - access denied
  963. ;          ebx = bytes written
  964. ;-----------------------------------------------------
  965.     cmp   [fat_type],0
  966.     jnz   append_fat_ok
  967.     mov   eax,ERROR_UNKNOWN_FS
  968.     ret
  969.  
  970.   append_fat_ok:
  971. ;    call  reserve_hd1
  972.  
  973.     pushad
  974.  
  975.     mov   ebx,edx
  976.     call  get_cluster_of_a_path
  977.     jc    append_not_found
  978.  
  979.     mov   ebx,PUSHAD_EAX        ; file name
  980.     call  analyze_directory
  981.     jc    append_not_found
  982.  
  983.     mov   [sector_tmp],eax
  984.     mov   [entry_pos],ebx
  985.  
  986.     test  byte [ebx+11],0x10    ; is it directory?
  987.     jnz   append_access         ; yes
  988.  
  989.     mov   ecx,[ebx+28]          ; file size
  990.     mov   edi,PUSHAD_ESI        ; write position
  991.     cmp   edi,-1                ; -1 = eof
  992.     jnz   append_inside_file
  993.     mov   edi,ecx               ; file size
  994.  
  995.   append_inside_file:
  996.     cmp   edi,ecx               ; start above old file size?
  997.     ja    append_eof            ; yes
  998.  
  999.     mov   [old_filesize],ecx
  1000.     mov   [new_filepos],edi
  1001.  
  1002.     mov   ecx,PUSHAD_EBX        ; bytes to write
  1003.     test  ecx,ecx               ; truncate?
  1004.     jz    append_truncate       ; yes
  1005.  
  1006.     mov   [bytes2write],ecx     ; bytes to write
  1007.     mov   esi,PUSHAD_ECX        ; pointer to buffer
  1008.     mov   eax,[ebx+20-2]        ; FAT entry
  1009.     mov   ax,[ebx+26]
  1010.     and   eax,[fatMASK]
  1011.     jnz   append_find_pos       ; first cluster <> 0
  1012.  
  1013.     mov   eax,2
  1014.     call  get_free_FAT
  1015.     jc    append_disk_full
  1016.     mov   ecx,eax               ; set files first cluster
  1017.     mov   [ebx+26],cx           ; 16 bits low of cluster
  1018.     shr   ecx,16
  1019.     mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
  1020.     mov   edx,[fatEND]          ; new end for cluster chain
  1021.     call  set_FAT
  1022.  
  1023.     push  eax                   ; save first cluster
  1024.     mov   eax,[sector_tmp]
  1025.     mov   ebx,buffer
  1026.     call  hd_write              ; write new file entry back to disk
  1027.     pop   eax
  1028.  
  1029.   append_remove_free:
  1030.     mov   ecx,-1                ; remove 1 cluster from free disk space
  1031.     call  add_disk_free_space   ; Note: uses buffer
  1032.  
  1033.   append_found_cluster:
  1034.     mov   [cluster],eax
  1035.     sub   eax,2
  1036.     mov   ecx,[SECTORS_PER_CLUSTER]
  1037.     imul  eax,ecx
  1038.     add   eax,[DATA_START]
  1039.     xor   edi,edi
  1040.  
  1041.   append_new_sector:
  1042.     push  ecx
  1043.     mov   ecx,[bytes2write]     ; bytes left in buffer
  1044.     mov   ebx,512
  1045.     sub   ebx,edi               ; bytes left in sector
  1046.     cmp   ecx,ebx
  1047.     jb    append_bytes_ok
  1048.     mov   ecx,ebx
  1049.  
  1050.   append_bytes_ok:
  1051.     cmp   ecx,512               ; overwrite full sector?
  1052.     jz    append_full_sector    ; yes
  1053.     mov   ebx,buffer            ; overwrite part of sector
  1054.     call  hd_read               ; read old sector
  1055.  
  1056.   append_full_sector:
  1057.     sub   [bytes2write],ecx
  1058.     add   [new_filepos],ecx
  1059.     add   edi,buffer
  1060.     cld
  1061.     rep   movsb
  1062.     pop   ecx
  1063.  
  1064.     mov   ebx,buffer
  1065.     call  hd_write
  1066.     cmp   [bytes2write],0       ; is all done?
  1067.     jz    append_done
  1068.     xor   edi,edi
  1069.     inc   eax
  1070.     dec   ecx
  1071.     jnz   append_new_sector
  1072.  
  1073.     mov   eax,[cluster]
  1074.     call  get_FAT
  1075.     cmp   eax,2
  1076.     jb    append_fat
  1077.     cmp   eax,[LAST_CLUSTER]
  1078.     jbe   append_found_cluster
  1079.  
  1080.   append_alloc_cluster:
  1081.     mov   eax,2                 ; ToDo: use temp array to keep track
  1082.     call  get_free_FAT          ;       of last free cluster
  1083.     jc    append_disk_full
  1084.     push  eax                   ; save new cluster
  1085.     mov   edx,[fatEND]          ; new end for cluster chain
  1086.     call  set_FAT
  1087.     mov   edx,eax
  1088.     mov   eax,[cluster]
  1089.     mov   [f_del],1
  1090.     call  set_FAT               ; update previous cluster
  1091.     mov   [f_del],0
  1092.     pop   eax
  1093.     jmp   append_remove_free
  1094.  
  1095.   append_find_pos:
  1096.     call  find_filepos
  1097.     mov   [cluster],ebx
  1098.     jnc   append_new_sector
  1099.     test  edi,edi
  1100.     jz    append_alloc_cluster
  1101.  
  1102.   append_fat:
  1103.     mov   eax,ERROR_FAT_TABLE
  1104.     jmp   append_ret_code
  1105.  
  1106.   append_disk_full:
  1107.     mov   eax,ERROR_DISK_FULL
  1108.     jmp   append_ret_code
  1109.  
  1110.   append_done:
  1111.     xor   eax,eax
  1112.  
  1113.   append_ret_code:
  1114.     mov   PUSHAD_EAX,eax        ; return code
  1115.  
  1116.     mov   eax,[sector_tmp]      ; update directory entry
  1117.     mov   ebx,buffer
  1118.     call  hd_read
  1119.     mov   ebx,[entry_pos]
  1120.     mov   ecx,[new_filepos]
  1121.     cmp   ecx,[old_filesize]    ; is file pos above old size?
  1122.     jbe   append_size_ok        ; no
  1123.     mov   [ebx+28],ecx          ; new file size
  1124.  
  1125.   append_size_ok:
  1126.     call  set_current_time_for_entry
  1127.     mov   ebx,buffer
  1128.     call  hd_write              ; write new file entry back to disk
  1129.  
  1130.     sub   ecx,PUSHAD_ESI        ; start position
  1131.     mov   PUSHAD_EBX,ecx        ; bytes written
  1132.     popad
  1133.     call  update_disk           ; write all of cache and fat to hd
  1134.     mov   [hd1_status],0
  1135.     ret
  1136.  
  1137.   append_eof:
  1138.     popad
  1139.     mov   [hd1_status],0
  1140.     xor   ebx,ebx
  1141.     mov   eax,ERROR_END_OF_FILE
  1142.     ret
  1143.  
  1144.   append_not_found:
  1145.     popad
  1146.     mov   [hd1_status],0
  1147.     xor   ebx,ebx
  1148.     mov   eax,ERROR_FILE_NOT_FOUND
  1149.     ret
  1150.  
  1151.   append_access:
  1152.     popad
  1153.     mov   [hd1_status],0
  1154.     xor   ebx,ebx
  1155.     mov   eax,ERROR_ACCESS_DENIED
  1156.     ret
  1157.  
  1158.   append_truncate:
  1159.     mov   edx,[ebx+20-2]        ; FAT entry
  1160.     mov   dx,[ebx+26]
  1161.     and   edx,[fatMASK]
  1162.     mov   [ebx+28],edi          ; set new file size
  1163.     test  edi,edi               ; 0 length file?
  1164.     jnz   truncate_save_size    ; no
  1165.     mov   [ebx+20],di           ; FAT entry = 0
  1166.     mov   [ebx+26],di
  1167.  
  1168.   truncate_save_size:
  1169.     call  set_current_time_for_entry
  1170.     mov   ebx,buffer
  1171.     call  hd_write
  1172.     mov   eax,edx               ; first cluster
  1173.     test  edi,edi               ; 0 length file?
  1174.     jz    truncate_clear_chain
  1175.  
  1176.     imul  esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes
  1177.  
  1178.   truncate_new_cluster:
  1179.     cmp   eax,2                 ; incorrect fat chain?
  1180.     jb    truncate_eof          ; yes
  1181.     cmp   eax,[fatRESERVED]     ; is it end of file?
  1182.     jnb   truncate_eof          ; yes
  1183.     sub   edi,esi
  1184.     jbe   truncate_pos_found
  1185.     call  get_FAT               ; get next cluster
  1186.     jmp   truncate_new_cluster
  1187.  
  1188.   truncate_pos_found:
  1189.     mov   edx,[fatEND]          ; new end for cluster chain
  1190.     mov   [f_del],1
  1191.     call  set_FAT
  1192.     mov   [f_del],0
  1193.     mov   eax,edx               ; clear rest of chain
  1194.  
  1195.   truncate_clear_chain:
  1196.     call  clear_cluster_chain
  1197.  
  1198.   truncate_eof:
  1199.     popad
  1200.     call  update_disk           ; write all of cache and fat to hd
  1201.     mov   [hd1_status],0
  1202.     xor   ebx,ebx
  1203.     xor   eax,eax
  1204.     ret
  1205.  
  1206.  
  1207. find_filepos:
  1208. ;-----------------------------------------------------
  1209. ; input  : eax = first cluster
  1210. ;          edi = bytes to skip over (start position)
  1211. ; output : if CARRY=0 file position found
  1212. ;          if CARRY=1 end of file found
  1213. ;          eax = current file sector
  1214. ;          ebx = last cluster
  1215. ;          ecx = sector count in last cluster
  1216. ;          edi = bytes to skip over (sector position)
  1217. ;-----------------------------------------------------
  1218.     push  esi
  1219.     mov   ecx,[SECTORS_PER_CLUSTER]
  1220.     imul  esi,ecx,512           ; esi = cluster size in bytes
  1221.     mov   ebx,eax
  1222.  
  1223.   filepos_new_cluster:
  1224.     cmp   eax,2                 ; incorrect fat chain?
  1225.     jb    filepos_eof           ; yes
  1226.     cmp   eax,[fatRESERVED]     ; is it end of file?
  1227.     jnb   filepos_eof           ; yes
  1228.  
  1229.     mov   ebx,eax
  1230.     cmp   edi,esi               ; skip over full cluster?
  1231.     jb    filepos_cluster_ok    ; no
  1232.  
  1233.     sub   edi,esi
  1234.     call  get_FAT               ; get next cluster
  1235.     jmp   filepos_new_cluster
  1236.  
  1237.   filepos_cluster_ok:
  1238.     sub   eax,2
  1239.     imul  eax,ecx
  1240.     add   eax,[DATA_START]
  1241.  
  1242.   filepos_new_sector:
  1243.     cmp   edi,512               ; skip over full sector?
  1244.     jb    filepos_sector_ok     ; no
  1245.     sub   edi,512
  1246.     inc   eax
  1247.     dec   ecx
  1248.     jnz   filepos_new_sector
  1249.  
  1250.   filepos_eof:
  1251.     pop   esi
  1252.     stc
  1253.     ret
  1254.  
  1255.   filepos_sector_ok:
  1256.     pop   esi
  1257.     clc
  1258.     ret
  1259.  
  1260.  
  1261. file_write:
  1262. ;--------------------------------------------------------------------------
  1263. ;   INPUT : user-reg  register-in-this  meaning      symbol-in-this-routine
  1264. ;
  1265. ;            EAX        EDI            system call to write    /
  1266. ;            EBX        EAX   (PAR0)   pointer to file-name    PAR0
  1267. ;            EDX        ECX   (PAR1)   pointer to buffer       PAR1
  1268. ;            ECX        EBX   (PAR2)   file size               PAR2
  1269. ;            ESI        EDX   (PAR3)   pointer to path         PAR3
  1270. ;
  1271. ; output : eax = 0 - ok
  1272. ;                3 - unknown FS
  1273. ;                5 - file not found
  1274. ;                8 - disk full
  1275. ;               10 - access denied
  1276. ;--------------------------------------------------------------------------
  1277.     cmp   [fat_type],0
  1278.     jnz   fat_ok_for_writing
  1279.     mov   eax,ERROR_UNKNOWN_FS
  1280.     ret
  1281.  
  1282.   fat_ok_for_writing:
  1283. ;    call  reserve_hd1
  1284.  
  1285.     pushad
  1286.  
  1287.     xor   edi,edi               ; don't allow directory remove
  1288.     call  file_delete           ; try to delete the file first
  1289.     test  eax,eax
  1290.     jz    old_deleted           ; deleted ok
  1291.     cmp   eax,ERROR_FILE_NOT_FOUND
  1292.     jnz   exit_write_access     ; it exist but can't delete
  1293.  
  1294.   old_deleted:
  1295.     mov   ebx,PUSHAD_EDX
  1296.     call  get_cluster_of_a_path
  1297.     jnc   found_directory_for_writing
  1298.  
  1299.   exit_writing_with_error:
  1300.     popad
  1301.     call  update_disk           ; write all of cache and fat to hd
  1302.     mov   [hd1_status],0
  1303.     mov   eax,ERROR_FILE_NOT_FOUND
  1304.     ret
  1305.  
  1306.   exit_writing_disk_full_clear:
  1307.     mov   eax,[sector_tmp]
  1308.     mov   ebx,buffer
  1309.     call  hd_read               ; read directory sector
  1310.     mov   edx,[entry_pos]
  1311.     mov   byte [edx],0xe5       ; mark as deleted
  1312.     call  hd_write
  1313.     mov   eax,[edx+20-2]        ; FAT entry
  1314.     mov   ax,[edx+26]
  1315.     and   eax,[fatMASK]
  1316.     call  clear_cluster_chain
  1317.  
  1318.   exit_writing_disk_full:
  1319.     popad
  1320.     call  update_disk           ; write all of cache and fat to hd
  1321.     mov   [hd1_status],0
  1322.     mov   eax,ERROR_DISK_FULL
  1323.     ret
  1324.  
  1325.   exit_write_access:
  1326.     popad
  1327.     call  update_disk           ; write all of cache and fat to hd
  1328.     mov   [hd1_status],0
  1329.     mov   eax,ERROR_ACCESS_DENIED
  1330.     ret
  1331.  
  1332. found_directory_for_writing:
  1333.     call  analyze_directory_to_write
  1334.     jc    exit_writing_disk_full
  1335.  
  1336.     mov   [sector_tmp],eax
  1337.     mov   [entry_pos],ebx
  1338.     push  eax                   ; save directory sector
  1339.     mov   eax,2
  1340.     call  get_free_FAT
  1341.     mov   [cluster],eax         ; first free cluster
  1342.     pop   eax
  1343.     jc    exit_writing_disk_full
  1344.  
  1345.     mov   esi,PUSHAD_EAX        ; file name
  1346.     mov   edi,ebx               ; pointer in buffer
  1347.     mov   ecx,11
  1348.     cld
  1349.     rep   movsb
  1350.  
  1351.     mov   esi,PUSHAD_EBX        ; file size (bytes left)
  1352.     mov   [ebx+28],esi          ; file size
  1353.     mov   ecx,[cluster]
  1354.     mov   [ebx+26],cx           ; 16 bits low of cluster
  1355.     shr   ecx,16
  1356.     mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
  1357.     mov   byte [ebx+11],0x20    ; attribute = archive
  1358.  
  1359.     call  set_current_time_for_entry
  1360.  
  1361.     mov   ebx,buffer            ; save the directory name,length,cluster
  1362.     call  hd_write
  1363.  
  1364.     imul  edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes
  1365.     xor   ecx,ecx               ; cluster count
  1366.     mov   ebx,PUSHAD_ECX        ; ebx = buffer
  1367.  
  1368. hd_new_block_write:
  1369.  
  1370.     mov   eax,[cluster]         ; eax = block
  1371.     call  set_data_cluster
  1372.  
  1373.     sub   esi,edi               ; sub wrote bytes
  1374.     jbe   file_saved_OK         ; end if all done
  1375.     add   ebx,edi               ; update buffer position
  1376.  
  1377.     inc   eax
  1378.     call  get_free_FAT          ; next free in FAT
  1379.     jc    exit_writing_disk_full_clear
  1380.  
  1381.     mov   edx,eax
  1382.     xchg  eax,[cluster]         ; get old cluster and save new cluster
  1383.     call  set_FAT               ; add it in cluster chain
  1384.     dec   ecx                   ; update cluster count
  1385.     jmp   hd_new_block_write
  1386.  
  1387. file_saved_OK:
  1388.  
  1389.     mov   edx,[fatEND]          ; new end for cluster chain
  1390.     call  set_FAT
  1391.     dec   ecx                   ; update cluster count
  1392.  
  1393.     call  add_disk_free_space   ; remove clusters from free disk space
  1394.  
  1395.     popad
  1396.     call  update_disk           ; write all of cache and fat to hd
  1397.     mov   [hd1_status],0
  1398.     xor   eax,eax
  1399.     ret
  1400.  
  1401.  
  1402. file_read:
  1403. ;--------------------------------------------------------------------------
  1404. ;   INPUT :  user-register register-in-this  meaning         symbol-in-this
  1405. ;
  1406. ;            EAX           EDI               system call to write   /
  1407. ;            EBX           EAX   (PAR0)      pointer to file-name   PAR0
  1408. ;            EDX           ECX   (PAR1)      pointer to buffer      PAR1
  1409. ;            ECX           EBX   (PAR2)   vt file blocks to read    PAR2
  1410. ;            ESI           EDX   (PAR3)      pointer to path        PAR3
  1411. ;            EDI           ESI            vt first 512 block to read
  1412. ;                          EDI               if 0 - read root
  1413. ;
  1414. ; output : eax = 0 - ok
  1415. ;                3 - unknown FS
  1416. ;                5 - file not found
  1417. ;                6 - end of file
  1418. ;                9 - fat table corrupted
  1419. ;          ebx = size of file/directory
  1420. ;--------------------------------------------------------------------------
  1421.     cmp   [fat_type],0
  1422.     jnz   fat_ok_for_reading
  1423.     xor   ebx,ebx
  1424.     mov   eax,ERROR_UNKNOWN_FS
  1425.     mov   [hd1_status], ebx
  1426.     ret
  1427.  
  1428.   fat_ok_for_reading:
  1429. ;    call  reserve_hd1
  1430.  
  1431.     pushad
  1432.  
  1433.     mov   ebx,edx
  1434.     call  get_cluster_of_a_path
  1435.     jc    file_to_read_not_found
  1436.  
  1437.     test  edi,edi               ; read rootdir
  1438.     jne   no_read_root
  1439.  
  1440.     xor   eax,eax
  1441.     call  get_dir_size          ; return rootdir size
  1442.     mov   [file_size],eax
  1443.     mov   eax,[ROOT_CLUSTER]
  1444.     jmp   file_read_start
  1445.  
  1446.   no_read_root:
  1447.     mov   ebx,PUSHAD_EAX        ; file name
  1448.     call  analyze_directory
  1449.     jc    file_to_read_not_found
  1450.  
  1451.     mov   eax,[ebx+28]          ; file size
  1452.     test  byte [ebx+11],0x10    ; is it directory?
  1453.     jz    read_set_size         ; no
  1454.  
  1455.     mov   eax,[ebx+20-2]        ; FAT entry
  1456.     mov   ax,[ebx+26]
  1457.     and   eax,[fatMASK]
  1458.     call  get_dir_size
  1459.  
  1460.   read_set_size:
  1461.     mov   [file_size],eax
  1462.  
  1463.     mov   eax,[ebx+20-2]        ; FAT entry
  1464.     mov   ax,[ebx+26]
  1465.     and   eax,[fatMASK]
  1466.  
  1467.   file_read_start:
  1468.     mov   ebx,PUSHAD_ECX        ; pointer to buffer
  1469.     mov   edx,PUSHAD_EBX        ; file blocks to read
  1470.     mov   esi,PUSHAD_ESI        ; first 512 block to read
  1471.  
  1472.   file_read_new_cluster:
  1473.     call  get_data_cluster
  1474.     jc    file_read_eof         ; end of file or cluster out of range
  1475.  
  1476.     test  edx,edx               ; is all read?
  1477.     je    file_read_OK          ; yes
  1478.  
  1479.     call  get_FAT               ; get next cluster
  1480.     cmp   eax,[fatRESERVED]     ; end of file
  1481.     jnb   file_read_eof
  1482.     cmp   eax,2                 ; incorrect fat chain
  1483.     jnb   file_read_new_cluster
  1484.  
  1485.     popad
  1486.     mov   [hd1_status],0
  1487.     mov   ebx,[file_size]
  1488.     mov   eax,ERROR_FAT_TABLE
  1489.     ret
  1490.  
  1491.   file_read_eof:
  1492.     popad
  1493.     mov   [hd1_status],0
  1494.     mov   ebx,[file_size]
  1495.     mov   eax,ERROR_END_OF_FILE
  1496.     ret
  1497.  
  1498.   file_read_OK:
  1499.     popad
  1500.     mov   [hd1_status],0
  1501.     mov   ebx,[file_size]
  1502.     xor   eax,eax
  1503.     ret
  1504.  
  1505.   file_to_read_not_found:
  1506.     popad
  1507.     mov   [hd1_status],0
  1508.     xor   ebx,ebx
  1509.     mov   eax,ERROR_FILE_NOT_FOUND
  1510.     ret
  1511.  
  1512.  
  1513. get_dir_size:
  1514. ;-----------------------------------------------------
  1515. ; input  : eax = first cluster (0=rootdir)
  1516. ; output : eax = directory size in bytes
  1517. ;-----------------------------------------------------
  1518.     push  edx
  1519.     xor   edx,edx               ; count of directory clusters
  1520.     test  eax,eax
  1521.     jnz   dir_size_next
  1522.  
  1523.     mov   eax,[ROOT_SECTORS]
  1524.     shl   eax,9                 ; fat16 rootdir size in bytes
  1525.     cmp   [fat_type],16
  1526.     je    dir_size_ret
  1527.     mov   eax,[ROOT_CLUSTER]
  1528.  
  1529.   dir_size_next:
  1530.     cmp   eax,2                 ; incorrect fat chain
  1531.     jb    dir_size_end
  1532.     cmp   eax,[fatRESERVED]     ; end of directory
  1533.     ja    dir_size_end
  1534.     call  get_FAT               ; get next cluster
  1535.     inc   edx
  1536.     jmp   dir_size_next
  1537.  
  1538.   dir_size_end:
  1539.     imul  eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
  1540.     imul  eax,edx
  1541.  
  1542.   dir_size_ret:
  1543.     pop   edx
  1544.     ret
  1545.  
  1546.  
  1547. file_delete:
  1548. ;-----------------------------------------------------
  1549. ; input  : eax = file/directory name
  1550. ;          edx = path
  1551. ;          edi = 1 - allow directory remove else don't remove directory
  1552. ; output : eax = 0 - ok
  1553. ;                3 - unknown FS
  1554. ;                5 - file not found
  1555. ;               10 - access denied
  1556. ;-----------------------------------------------------
  1557.     cmp   [fat_type],0
  1558.     jnz   file_del_fat_ok
  1559.     mov   eax,ERROR_UNKNOWN_FS
  1560.     ret
  1561.  
  1562.   file_del_fat_ok:
  1563.     pushad
  1564.  
  1565.     mov   ebx,edx
  1566.     call  get_cluster_of_a_path
  1567.     jc    file_to_delete_not_found
  1568.  
  1569.     mov   ebx,PUSHAD_EAX        ; file/directory name
  1570.     call  analyze_directory
  1571.     jc    file_to_delete_not_found
  1572.  
  1573.     test  byte [ebx+11],0x10    ; is it directory?
  1574.     jz    delete_notdir         ; no. it's file
  1575.     cmp   edi,1                 ; allow directory remove
  1576.     jnz   delete_no_access      ; no
  1577.  
  1578.     push  eax                   ; save directory sector
  1579.     mov   eax,[ebx+20-2]        ; first cluster of file
  1580.     mov   ax,[ebx+26]           ; 0 length files start cluster = 0
  1581.     and   eax,[fatMASK]
  1582.     xor   ebp,ebp               ; counter for directory deepnes
  1583.     call  clear_directory
  1584.     pop   eax
  1585.     jc    delete_no_access
  1586.  
  1587.     push  ebx                   ; save directory pointer in buffer
  1588.     mov   ebx,buffer
  1589.     call  hd_read               ; read directory sector
  1590.     pop   ebx
  1591.  
  1592.   delete_notdir:
  1593.     call  delete_entry_name
  1594.     mov   eax,ecx               ; first cluster of file
  1595.     call  clear_cluster_chain
  1596.     popad
  1597.     xor   eax,eax
  1598.     ret
  1599.  
  1600.   delete_no_access:
  1601.     popad
  1602.     mov   eax,ERROR_ACCESS_DENIED
  1603.     ret
  1604.  
  1605.   file_to_delete_not_found:
  1606.     popad
  1607.     mov   eax,ERROR_FILE_NOT_FOUND
  1608.     ret
  1609.  
  1610.  
  1611. clear_cluster_chain:
  1612. ;-----------------------------------------------------
  1613. ; input  : eax = first cluster
  1614. ;-----------------------------------------------------
  1615.     push  eax ecx edx
  1616.     xor   ecx,ecx               ; cluster count
  1617.     mov   [f_del],1             ; delete on
  1618.  
  1619.   clean_new_chain:
  1620.     cmp   eax,[LAST_CLUSTER]    ; end of file
  1621.     ja    delete_OK
  1622.     cmp   eax,2                 ; unfinished fat chain or zero length file
  1623.     jb    delete_OK
  1624.     cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
  1625.     jz    delete_OK
  1626.  
  1627.     xor   edx,edx
  1628.     call  set_FAT               ; clear fat entry
  1629.     inc   ecx                   ; update cluster count
  1630.     mov   eax,edx               ; old cluster
  1631.     jmp   clean_new_chain
  1632.  
  1633.   delete_OK:
  1634.     call  add_disk_free_space   ; add clusters to free disk space
  1635.     mov   [f_del],0
  1636.     pop   edx ecx eax
  1637.     ret
  1638.  
  1639.  
  1640. clear_directory:
  1641. ;-----------------------------------------------------
  1642. ; input  : eax = directory cluster
  1643. ;          ebp = directory deepnes
  1644. ; Note   : use recursive call
  1645. ;-----------------------------------------------------
  1646.     pushad
  1647.     inc   ebp
  1648.     cmp   ebp,64                ; if over 63 directory deep
  1649.     jnb   clear_error           ; something must be wrong
  1650.  
  1651.   clear_new_cluster:
  1652.     cmp   eax,[LAST_CLUSTER]
  1653.     ja    clear_end
  1654.     cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
  1655.     jz    clear_end
  1656.     mov   esi,eax               ; esi = current directory cluster
  1657.     sub   eax,2
  1658.     jb    clear_end
  1659.     mov   ecx,[SECTORS_PER_CLUSTER]
  1660.     imul  eax,ecx
  1661.     add   eax,[DATA_START]
  1662.  
  1663.   clear_new_sector:
  1664.     mov   edi,eax               ; edi = current directory sector
  1665.     mov   ebx,deltree_buffer
  1666.     call  hd_read
  1667.     mov   edx,512/32            ; count of dir entrys per sector = 16
  1668.  
  1669.   clear_analyze:
  1670.     mov   al,[ebx+11]           ; file attribute
  1671.     and   al,0xf
  1672.     cmp   al,0xf
  1673.     je    clear_long_filename
  1674.  
  1675.     cmp   byte [ebx],'.'        ; parent or current directory
  1676.     je    clear_next_entry
  1677.     cmp   byte [ebx],0xe5       ; deleted
  1678.     je    clear_next_entry
  1679.     cmp   byte [ebx],0          ; empty
  1680.     je    clear_write_last
  1681.     ;je    clear_next_entry
  1682.  
  1683.     mov   eax,[ebx+20-2]        ; first cluster of entry
  1684.     mov   ax,[ebx+26]
  1685.     and   eax,[fatMASK]
  1686.  
  1687.     test  byte [ebx+11],0x10    ; is it directory?
  1688.     jz    clear_file            ; no
  1689.  
  1690.     push  eax ebx
  1691.     mov   eax,edi
  1692.     mov   ebx,deltree_buffer    ; save buffer over recursive call
  1693.     call  hd_write              ; write directory sector to disk
  1694.     pop   ebx eax
  1695.  
  1696.     call  clear_directory       ; recursive call !!!
  1697.     jc    clear_error           ; exit if error found
  1698.  
  1699.     push  eax ebx
  1700.     mov   eax,edi
  1701.     mov   ebx,deltree_buffer
  1702.     call  hd_read               ; read directory sector again
  1703.     pop   ebx eax
  1704.  
  1705.   clear_file:
  1706.     call  clear_cluster_chain
  1707.  
  1708.   clear_long_filename:
  1709.     mov   byte [ebx],0xe5
  1710.  
  1711.   clear_next_entry:
  1712.     add   ebx,32                ; position of next dir entry
  1713.     dec   edx
  1714.     jnz   clear_analyze
  1715.  
  1716.     mov   eax,edi
  1717.     mov   ebx,deltree_buffer
  1718.     call  hd_write              ; write directory sector to disk
  1719.  
  1720.     inc   eax                   ; next sector
  1721.     dec   ecx
  1722.     jnz   clear_new_sector
  1723.  
  1724.     mov   eax,esi
  1725.     call  get_FAT               ; get next cluster
  1726.     jmp   clear_new_cluster     ; clear it
  1727.  
  1728.   clear_write_last:
  1729.     mov   eax,edi
  1730.     mov   ebx,deltree_buffer
  1731.     call  hd_write              ; write directory sector to disk
  1732.  
  1733.   clear_end:
  1734.     popad
  1735.     clc
  1736.     ret
  1737.  
  1738.   clear_error:
  1739.     popad
  1740.     stc
  1741.     ret
  1742.  
  1743.  
  1744. delete_entry_name:
  1745. ;-----------------------------------------------------
  1746. ; input  : eax = directory sector
  1747. ;          ebx = directory pointer in buffer
  1748. ;          longname_sec = 2 previous directory sectors
  1749. ; output : ecx = first cluster
  1750. ; change : eax,ebx,edx
  1751. ;-----------------------------------------------------
  1752.     mov   byte [ebx],0xe5
  1753.     mov   ecx,[ebx+20-2]        ; first cluster of file
  1754.     mov   cx,[ebx+26]           ; 0 length files start cluster = 0
  1755.     and   ecx,[fatMASK]
  1756.  
  1757.   delete_empty:
  1758.     sub   ebx,32
  1759.     cmp   ebx,buffer
  1760.     jnb   delete_test_long
  1761.  
  1762.     mov   ebx,buffer
  1763.     call  hd_write              ; write directory sector back
  1764.     xor   eax,eax
  1765.     xchg  eax,[longname_sec2]
  1766.     xchg  eax,[longname_sec1]
  1767.     test  eax,eax               ; is there previous directory sector?
  1768.     jz    delete_name_end       ; no
  1769.  
  1770.     mov   ebx,buffer
  1771.     call  hd_read               ; read previous sector
  1772.     mov   ebx,buffer+0x1e0      ; start from last entry
  1773.  
  1774.   delete_test_long:
  1775.     mov   dh,[ebx+11]           ; file attribute
  1776.     and   dh,0xf
  1777.     cmp   dh,0xf
  1778.     jne   delete_write_buffer
  1779.  
  1780.     cmp   byte [ebx],0x40       ; end of long dir entry?
  1781.     mov   byte [ebx],0xe5
  1782.     jb    delete_empty
  1783.  
  1784.   delete_write_buffer:
  1785.     mov   ebx,buffer
  1786.     call  hd_write              ; write directory sector back
  1787.  
  1788.   delete_name_end:
  1789.     ret
  1790.  
  1791.  
  1792. rename:
  1793. ;-----------------------------------------------------------
  1794. ; input  : eax = source directory name
  1795. ;          edx = source path
  1796. ;          ebx = dest directory name
  1797. ;          edi = dest path
  1798. ; output : eax = 0 - ok
  1799. ;                3 - unknown FS
  1800. ;                5 - file not found
  1801. ;                8 - disk full
  1802. ;               10 - access denied
  1803. ;-----------------------------------------------------------
  1804.     cmp   [fat_type],0
  1805.     jnz   fat_ok_for_rename
  1806.     mov   eax,ERROR_UNKNOWN_FS
  1807.     ret
  1808.  
  1809.   fat_ok_for_rename:
  1810. ;    call  reserve_hd1
  1811.  
  1812.     pushad
  1813.  
  1814.     mov   ebx,edx               ; source path
  1815.     call  get_cluster_of_a_path
  1816.     jc    rename_entry_not_found
  1817.  
  1818.     mov   ebx,PUSHAD_EAX        ; source directory name
  1819.     call  analyze_directory
  1820.     jc    rename_entry_not_found
  1821.  
  1822.     mov   [sector_tmp],eax      ; save source sector
  1823.     mov   [entry_pos],ebx
  1824.     mov   esi,ebx
  1825.     mov   edi,dir_entry
  1826.     mov   ecx,32/4
  1827.     cld
  1828.     rep   movsd                 ; save entry
  1829.  
  1830.     mov   ebx,PUSHAD_EDI        ; dest path
  1831.     call  get_cluster_of_a_path
  1832.     jc    rename_entry_not_found
  1833.  
  1834.     mov   edx,eax               ; save dest directory cluster
  1835.     mov   ebx,PUSHAD_EBX        ; dest directory name
  1836.     push  [longname_sec1]
  1837.     push  [longname_sec2]
  1838.     call  analyze_directory     ; check if entry already exist
  1839.     pop   [longname_sec2]
  1840.     pop   [longname_sec1]
  1841.     jnc   rename_entry_already_exist
  1842.  
  1843.     mov   eax,edx
  1844.     call  analyze_directory_to_write
  1845.     jc    rename_disk_full
  1846.  
  1847.     mov   esi,dir_entry
  1848.     mov   edi,ebx
  1849.     mov   ecx,32/4
  1850.     cld
  1851.     rep   movsd                 ; copy entry
  1852.     mov   esi,PUSHAD_EBX        ; dest directory name
  1853.     mov   edi,ebx
  1854.     mov   ecx,11
  1855.     rep   movsb                 ; copy name
  1856.  
  1857.     mov   ebx,buffer            ; save the directory name,length,cluster
  1858.     call  hd_write
  1859.  
  1860.     test  byte [dir_entry+11],0x10 ; is it directory?
  1861.     jz    rename_not_dir           ; no
  1862.     mov   eax,[dir_entry+20-2]     ; FAT entry
  1863.     mov   ax,[dir_entry+26]
  1864.     and   eax,[fatMASK]
  1865.     call  change_2dot_cluster
  1866.  
  1867.   rename_not_dir:
  1868.     mov   eax,[sector_tmp]
  1869.     mov   ebx,buffer
  1870.     call  hd_read               ; read source directory sector
  1871.  
  1872.     mov   ebx,[entry_pos]
  1873.     call  delete_entry_name
  1874.  
  1875.     popad
  1876.     call  update_disk           ; write all of cache and fat to hd
  1877.     mov   [hd1_status],0
  1878.     xor   eax,eax
  1879.     ret
  1880.  
  1881.   rename_entry_not_found:
  1882.     popad
  1883.     mov   [hd1_status],0
  1884.     mov   eax,ERROR_FILE_NOT_FOUND
  1885.     ret
  1886.  
  1887.   rename_entry_already_exist:
  1888.     popad
  1889.     mov   [hd1_status],0
  1890.     mov   eax,ERROR_ACCESS_DENIED
  1891.     ret
  1892.  
  1893.   rename_disk_full:
  1894.     popad
  1895.     mov   [hd1_status],0
  1896.     mov   eax,ERROR_DISK_FULL
  1897.     ret
  1898.  
  1899.  
  1900. change_2dot_cluster:
  1901. ;-----------------------------------------------------------
  1902. ; input  : eax = directory cluster
  1903. ;          edx = value to save
  1904. ; change : eax,ebx,edx
  1905. ;-----------------------------------------------------------
  1906.     cmp   eax,[LAST_CLUSTER]
  1907.     ja    not_2dot              ; too big cluster number, something is wrong
  1908.     sub   eax,2
  1909.     jb    not_2dot
  1910.  
  1911.     imul  eax,[SECTORS_PER_CLUSTER]
  1912.     add   eax,[DATA_START]
  1913.     mov   ebx,buffer
  1914.     call  hd_read
  1915.  
  1916.     cmp   dword [ebx+32],'..  '
  1917.     jnz   not_2dot
  1918.  
  1919.     cmp   edx,[ROOT_CLUSTER]    ; is rootdir cluster?
  1920.     jne   not_2dot_root
  1921.     xor   edx,edx               ; yes. set it zero
  1922.  
  1923.   not_2dot_root:
  1924.     mov   [ebx+32+26],dx        ; 16 bits low of cluster
  1925.     shr   edx,16
  1926.     mov   [ebx+32+20],dx        ; 16 bits high of cluster (=0 fat16)
  1927.     call  hd_write
  1928.  
  1929.   not_2dot:
  1930.     ret
  1931.  
  1932.  
  1933. get_filesize:
  1934. ;-----------------------------------------------------------
  1935. ; input  : eax = file name
  1936. ;          edx = path
  1937. ;          edi = if 0 - read rootdir else normal dir/file size
  1938. ; output : eax = 0 - ok
  1939. ;                3 - unknown FS
  1940. ;                5 - file not found
  1941. ;          ebx = file size
  1942. ;-----------------------------------------------------------
  1943.     cmp   [fat_type],0
  1944.     jnz   get_filesize_fat_ok
  1945.     xor   ebx,ebx
  1946.     mov   eax,ERROR_UNKNOWN_FS
  1947.     ret
  1948.  
  1949.   get_filesize_fat_ok:
  1950. ;    call  reserve_hd1
  1951.  
  1952.     pushad
  1953.     xor   eax,eax
  1954.     test  edi,edi               ; is read rootdir?
  1955.     je    get_filesize_dirsize  ; yes
  1956.  
  1957.   get_filesize_no_root:
  1958.     mov   ebx,edx
  1959.     call  get_cluster_of_a_path
  1960.     jc    get_filesize_not_found
  1961.  
  1962.     mov   ebx,PUSHAD_EAX        ; file name
  1963.     call  analyze_directory
  1964.     jc    get_filesize_not_found
  1965.  
  1966.     mov   eax,[ebx+28]          ; file size
  1967.     test  byte [ebx+11],0x10    ; is it directory?
  1968.     jz    get_filesize_set_size ; no
  1969.  
  1970.     mov   eax,[ebx+20-2]        ; FAT entry
  1971.     mov   ax,[ebx+26]
  1972.     and   eax,[fatMASK]
  1973.  
  1974.   get_filesize_dirsize:
  1975.     call  get_dir_size
  1976.  
  1977.   get_filesize_set_size:
  1978.     mov   PUSHAD_EBX,eax
  1979.     popad
  1980.     mov   [hd1_status],0
  1981.     xor   eax,eax
  1982.     ret
  1983.  
  1984.   get_filesize_not_found:
  1985.     popad
  1986.     mov   [hd1_status],0
  1987.     xor   ebx,ebx
  1988.     mov   eax,ERROR_FILE_NOT_FOUND
  1989.     ret
  1990.  
  1991.  
  1992. get_fileattr:
  1993. ;-----------------------------------------------------------
  1994. ; input  : eax = file name
  1995. ;          edx = path
  1996. ; output : eax = 0 - ok
  1997. ;                3 - unknown FS
  1998. ;                5 - file not found
  1999. ;          ebx = file attribute
  2000. ;-----------------------------------------------------------
  2001.     cmp   [fat_type],0
  2002.     jnz   get_fileattr_fat_ok
  2003.     xor   ebx,ebx
  2004.     mov   eax,ERROR_UNKNOWN_FS
  2005.     ret
  2006.  
  2007.   get_fileattr_fat_ok:
  2008. ;    call  reserve_hd1
  2009.  
  2010.     pushad
  2011.     mov   ebx,edx
  2012.     call  get_cluster_of_a_path
  2013.     jc    get_fileattr_not_found
  2014.  
  2015.     mov   ebx,PUSHAD_EAX        ; file name
  2016.     call  analyze_directory
  2017.     jc    get_fileattr_not_found
  2018.  
  2019.     movzx eax,byte [ebx+11]     ; file attribute
  2020.     mov   PUSHAD_EBX,eax
  2021.     popad
  2022.     mov   [hd1_status],0
  2023.     xor   eax,eax
  2024.     ret
  2025.  
  2026.   get_fileattr_not_found:
  2027.     popad
  2028.     mov   [hd1_status],0
  2029.     xor   ebx,ebx
  2030.     mov   eax,ERROR_FILE_NOT_FOUND
  2031.     ret
  2032.  
  2033.  
  2034. get_filedate:
  2035. ;-----------------------------------------------------------
  2036. ; input  : eax = file name
  2037. ;          edx = path
  2038. ; output : eax = 0 - ok
  2039. ;                3 - unknown FS
  2040. ;                5 - file not found
  2041. ;          ebx = file date/time
  2042. ;                bits 31..25 = year-1980
  2043. ;                bits 24..21 = month
  2044. ;                bits 20..16 = day
  2045. ;                bits 15..11 = hour
  2046. ;                bits 10..5  = minute
  2047. ;                bits 4..0   = second/2
  2048. ;-----------------------------------------------------------
  2049.     cmp   [fat_type],0
  2050.     jnz   get_filedate_fat_ok
  2051.     xor   ebx,ebx
  2052.     mov   eax,ERROR_UNKNOWN_FS
  2053.     ret
  2054.  
  2055.   get_filedate_fat_ok:
  2056. ;    call  reserve_hd1
  2057.  
  2058.     pushad
  2059.     mov   ebx,edx
  2060.     call  get_cluster_of_a_path
  2061.     jc    get_filedate_not_found
  2062.  
  2063.     mov   ebx,PUSHAD_EAX        ; file name
  2064.     call  analyze_directory
  2065.     jc    get_filedate_not_found
  2066.  
  2067.     mov   eax,[ebx+22]          ; file date/time
  2068.     mov   PUSHAD_EBX,eax
  2069.     popad
  2070.     mov   [hd1_status],0
  2071.     xor   eax,eax
  2072.     ret
  2073.  
  2074.   get_filedate_not_found:
  2075.     popad
  2076.     mov   [hd1_status],0
  2077.     xor   ebx,ebx
  2078.     mov   eax,ERROR_FILE_NOT_FOUND
  2079.     ret
  2080.  
  2081.  
  2082. get_hd_info:
  2083. ;-----------------------------------------------------------
  2084. ; output : eax = 0 - ok
  2085. ;                3 - unknown FS
  2086. ;          edx = cluster size in bytes
  2087. ;          ebx = total clusters on disk
  2088. ;          ecx = free clusters on disk
  2089. ;-----------------------------------------------------------
  2090.     cmp   [fat_type],0
  2091.     jnz   info_fat_ok
  2092.     xor   edx,edx
  2093.     xor   ebx,ebx
  2094.     xor   ecx,ecx
  2095.     mov   eax,ERROR_UNKNOWN_FS
  2096.     ret
  2097.  
  2098.   info_fat_ok:
  2099. ;    call  reserve_hd1
  2100.  
  2101.     xor   ecx,ecx               ; count of free clusters
  2102.     mov   eax,2
  2103.     mov   ebx,[LAST_CLUSTER]
  2104.  
  2105.   info_cluster:
  2106.     push  eax
  2107.     call  get_FAT               ; get cluster info
  2108.     test  eax,eax               ; is it free?
  2109.     jnz   info_used             ; no
  2110.     inc   ecx
  2111.  
  2112.   info_used:
  2113.     pop   eax
  2114.     inc   eax
  2115.     cmp   eax,ebx               ; is above last cluster?
  2116.     jbe   info_cluster          ; no. test next cluster
  2117.  
  2118.     dec   ebx                   ; cluster count
  2119.     imul  edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
  2120.     mov   [hd1_status],0
  2121.     xor   eax,eax
  2122.     ret
  2123.  
  2124.  
  2125. update_disk:
  2126. ;-----------------------------------------------------------
  2127. ; write changed fat and cache to disk
  2128. ;-----------------------------------------------------------
  2129.     cmp   [fat_change],0        ; is fat changed?
  2130.     je    upd_no_change
  2131.  
  2132.     call  write_fat_sector
  2133.  
  2134.   upd_no_change:
  2135.  
  2136.     call  write_cache
  2137.     ret
  2138.  
  2139.  
  2140. ;**************************************************************************
  2141. ;
  2142. ;   0x600008  - first entry in cache list
  2143. ;
  2144. ;            +0   - lba sector
  2145. ;            +4   - state of cache sector
  2146. ;                   0 = empty
  2147. ;                   1 = used for read  ( same as in hd )
  2148. ;                   2 = used for write ( differs from hd )
  2149. ;
  2150. ;      +65536 - cache entries
  2151. ;
  2152. ;**************************************************************************
  2153.  
  2154.  
  2155. hd_read:
  2156. ;-----------------------------------------------------------
  2157. ; input  : eax = block to read
  2158. ;          ebx = destination
  2159. ;-----------------------------------------------------------
  2160.     push  ecx esi edi           ; scan cache
  2161.  
  2162.     mov   ecx,cache_max         ; entries in cache
  2163.     mov   esi,0x600000+8
  2164.     mov   edi,1
  2165.  
  2166.   hdreadcache:
  2167.  
  2168.     cmp   dword [esi+4],0       ; empty
  2169.     je    nohdcache
  2170.  
  2171.     cmp   [esi],eax             ; correct sector
  2172.     je    yeshdcache
  2173.  
  2174.   nohdcache:
  2175.  
  2176.     add   esi,8
  2177.     inc   edi
  2178.     dec   ecx
  2179.     jnz   hdreadcache
  2180.  
  2181.     call  find_empty_slot       ; ret in edi
  2182.  
  2183.     call  wait_for_hd_idle
  2184.     push  eax edx
  2185.  
  2186.     cli
  2187.     xor   eax,eax
  2188.     mov   edx,[hdbase]
  2189.     inc   edx
  2190.     out   dx,al   ; ATAFeatures ðåãèñòð "îñîáåííîñòåé"
  2191.     inc   edx
  2192.     inc   eax
  2193.     out   dx,al   ; ATASectorCount ñ÷åò÷èê ñåêòîðîâ
  2194.     inc   edx
  2195.     mov   eax,[esp+4]
  2196.     out   dx,al   ; ATASectorNumber ðåãèñòð íîìåðà ñåêòîðà
  2197.     shr   eax,8
  2198.     inc   edx
  2199.     out   dx,al   ; ATACylinder íîìåð öèëèíäðà (ìëàäøèé áàéò)
  2200.     shr   eax,8
  2201.     inc   edx
  2202.     out   dx,al   ; íîìåð öèëèíäðà (ñòàðøèé áàéò)
  2203.     shr   eax,8
  2204.     inc   edx
  2205.     and   al,1+2+4+8
  2206.     add   al,byte [hdid]
  2207.     add   al,128+64+32
  2208.     out   dx,al   ; íîìåð ãîëîâêè/íîìåð äèñêà
  2209.     inc   edx
  2210.     mov   al,20h
  2211.     out   dx,al   ; ATACommand ðåãèñòð êîìàíä
  2212.     sti
  2213.  
  2214.     call  wait_for_sector_buffer
  2215.  
  2216.     cmp   [hd_error],0
  2217.     jne   hd_read_error
  2218.  
  2219.     cli
  2220.     push  edi
  2221.     shl   edi,9
  2222.     add   edi,0x600000+65536
  2223.     mov   ecx,256
  2224.     mov   edx,[hdbase]
  2225.     cld
  2226.     rep   insw
  2227.     pop   edi
  2228.     sti
  2229.  
  2230.     pop   edx eax
  2231.  blok_read_2:
  2232.     lea   esi,[edi*8+0x600000]
  2233.     mov   [esi],eax             ; sector number
  2234.     mov   dword [esi+4],1       ; hd read - mark as same as in hd
  2235.  
  2236.   yeshdcache:
  2237.  
  2238.     mov   esi,edi
  2239.     shl   esi,9
  2240.     add   esi,0x600000+65536
  2241.     mov   edi,ebx
  2242.     mov   ecx,512/4
  2243.     cld
  2244.     rep   movsd                 ; move data
  2245. ; blok_read_2:
  2246.     pop   edi esi ecx
  2247.     ret
  2248.    
  2249.  
  2250. hd_write:
  2251. ;-----------------------------------------------------------
  2252. ; input  : eax = block
  2253. ;          ebx = pointer to memory
  2254. ;-----------------------------------------------------------
  2255.     push  ecx esi edi
  2256.  
  2257.     ; check if the cache already has the sector and overwrite it
  2258.  
  2259.     mov   ecx,cache_max
  2260.     mov   esi,0x600000+8
  2261.     mov   edi,1
  2262.  
  2263.   hdwritecache:
  2264.  
  2265.     cmp   dword [esi+4],0       ; if cache slot is empty
  2266.     je    not_in_cache_write
  2267.  
  2268.     cmp   [esi],eax             ; if the slot has the sector
  2269.     je    yes_in_cache_write
  2270.  
  2271.   not_in_cache_write:
  2272.  
  2273.     add   esi,8
  2274.     inc   edi
  2275.     dec   ecx
  2276.     jnz   hdwritecache
  2277.  
  2278.     ; sector not found in cache
  2279.     ; write the block to a new location
  2280.  
  2281.     call  find_empty_slot       ; ret in edi
  2282.  
  2283.     lea   esi,[edi*8+0x600000]
  2284.     mov   [esi],eax             ; sector number
  2285.  
  2286.   yes_in_cache_write:
  2287.  
  2288.     mov   dword [esi+4],2       ; write - differs from hd
  2289.  
  2290.     shl   edi,9
  2291.     add   edi,0x600000+65536
  2292.     mov   esi,ebx
  2293.     mov   ecx,512/4
  2294.     cld
  2295.     rep   movsd                 ; move data
  2296.  
  2297.     pop   edi esi ecx
  2298.     ret
  2299.  
  2300.  
  2301. write_cache:
  2302. ;-----------------------------------------------------------
  2303. ; write all changed sectors to disk
  2304. ;-----------------------------------------------------------
  2305.     push  eax ecx edx esi edi
  2306.  
  2307.     ; write difference ( 2 ) from cache to hd
  2308.  
  2309.     mov   ecx,cache_max
  2310.     mov   esi,0x600000+8
  2311.     mov   edi,1
  2312.  
  2313.   write_cache_more:
  2314.  
  2315.     cmp   dword [esi+4],2       ; if cache slot is not different
  2316.     jne   does_not_need_writing
  2317.  
  2318.     mov   dword [esi+4],1       ; same as in hd
  2319.     mov   eax,[esi]             ; eax = sector to write
  2320.  
  2321.     cmp   eax,[PARTITION_START]
  2322.     jb    danger
  2323.     cmp   eax,[PARTITION_END]
  2324.     ja    danger
  2325.  
  2326.     call  wait_for_hd_idle
  2327.  
  2328.     cli
  2329.     xor   eax,eax
  2330.     mov   edx,[hdbase]
  2331.     inc   edx
  2332.     out   dx,al
  2333.     inc   edx
  2334.     inc   eax
  2335.     out   dx,al
  2336.     inc   edx
  2337.     mov   eax,[esi]             ; eax = sector to write
  2338.     out   dx,al
  2339.     shr   eax,8
  2340.     inc   edx
  2341.     out   dx,al
  2342.     shr   eax,8
  2343.     inc   edx
  2344.     out   dx,al
  2345.     shr   eax,8
  2346.     inc   edx
  2347.     and   al,1+2+4+8
  2348.     add   al,byte [hdid]
  2349.     add   al,128+64+32
  2350.     out   dx,al
  2351.     inc   edx
  2352.     mov   al,30h
  2353.     out   dx,al
  2354.     sti
  2355.  
  2356.     call  wait_for_sector_buffer
  2357.  
  2358.     cmp   [hd_error],0
  2359.     jne   hd_write_error
  2360.  
  2361.     push  ecx esi
  2362.  
  2363.     cli
  2364.     mov   esi,edi
  2365.     shl   esi,9
  2366.     add   esi,0x600000+65536    ; esi = from memory position
  2367.     mov   ecx,256
  2368.     mov   edx,[hdbase]
  2369.     cld
  2370.     rep   outsw
  2371.     sti
  2372.  
  2373.     pop   esi ecx
  2374.  
  2375.   danger:
  2376.   does_not_need_writing:
  2377.  
  2378.     add   esi,8
  2379.     inc   edi
  2380.     dec   ecx
  2381.     jnz   write_cache_more
  2382.  
  2383.     pop   edi esi edx ecx eax
  2384.     ret
  2385.  
  2386.  
  2387. find_empty_slot:
  2388. ;-----------------------------------------------------------
  2389. ; find empty or read slot, flush cache if next 10% is used by write
  2390. ; output : edi = cache slot
  2391. ;-----------------------------------------------------------
  2392.     push  ecx esi
  2393.  
  2394.   search_again:
  2395.  
  2396.     mov   ecx,cache_max*10/100
  2397.     mov   edi,[cache_search_start]
  2398.  
  2399.   search_for_empty:
  2400.  
  2401.     inc   edi
  2402.     cmp   edi,cache_max
  2403.     jbe   inside_cache
  2404.     mov   edi,1
  2405.  
  2406.   inside_cache:
  2407.  
  2408.     cmp   dword [edi*8+0x600000+4],2    ; get cache slot info
  2409.     jb    found_slot                    ; it's empty or read
  2410.     dec   ecx
  2411.     jnz   search_for_empty
  2412.  
  2413.     call  write_cache                   ; no empty slots found, write all
  2414.     jmp   search_again                  ; and start again
  2415.  
  2416.   found_slot:
  2417.  
  2418.     mov   [cache_search_start],edi
  2419.  
  2420.     pop   esi ecx
  2421.     ret
  2422.  
  2423.  
  2424. save_hd_wait_timeout:
  2425.  
  2426.     push  eax
  2427.     mov   eax,[timer_ticks];[0xfdf0]
  2428.     add   eax,300               ; 3 sec timeout
  2429.     mov   [hd_wait_timeout],eax
  2430.     pop   eax
  2431.     ret
  2432.  
  2433.  
  2434. check_hd_wait_timeout:
  2435.  
  2436.     push  eax
  2437.     mov   eax,[hd_wait_timeout]
  2438.     cmp   [timer_ticks], eax ;[0xfdf0],eax
  2439.     jg    hd_timeout_error
  2440.     pop   eax
  2441.     ret
  2442.  
  2443. iglobal
  2444.   hd_timeout_str   db 'K : FS - HD timeout',13,10,0
  2445.   hd_read_str      db 'K : FS - HD read error',13,10,0
  2446.   hd_write_str     db 'K : FS - HD write error',13,10,0
  2447. endg
  2448.  
  2449. hd_timeout_error:
  2450.  
  2451.     call  clear_hd_cache
  2452.     call  clear_application_table_status
  2453.     mov   esi,hd_timeout_str
  2454.     call  sys_msg_board_str
  2455.     jmp   $
  2456.  
  2457.  
  2458. hd_read_error:
  2459.  
  2460.     call  clear_hd_cache
  2461.     call  clear_application_table_status
  2462.     mov   esi,hd_read_str
  2463.     call  sys_msg_board_str
  2464.     jmp   $
  2465.  
  2466. hd_write_error:
  2467.  
  2468.     call  clear_hd_cache
  2469.     call  clear_application_table_status
  2470.     mov   esi,hd_write_str
  2471.     call  sys_msg_board_str
  2472.     jmp   $
  2473.  
  2474.  
  2475.  
  2476.  
  2477. wait_for_hd_idle:
  2478.  
  2479.     push  eax edx
  2480.  
  2481.     call  save_hd_wait_timeout
  2482.  
  2483.     mov   edx,[hdbase]
  2484.     add   edx,0x7
  2485.  
  2486.   wfhil1:
  2487.  
  2488.     call  check_hd_wait_timeout
  2489.  
  2490.     in    al,dx
  2491.     test  al,128
  2492.     jnz   wfhil1
  2493.  
  2494.     pop   edx eax
  2495.     ret
  2496.  
  2497.  
  2498. wait_for_sector_buffer:
  2499.  
  2500.     push  eax edx
  2501.  
  2502.     mov   edx,[hdbase]
  2503.     add   edx,0x7
  2504.  
  2505.     call  save_hd_wait_timeout
  2506.  
  2507.   hdwait_sbuf:                  ; wait for sector buffer to be ready
  2508.  
  2509.     call  check_hd_wait_timeout
  2510.  
  2511.     in    al,dx
  2512.     test  al,8
  2513.     jz    hdwait_sbuf
  2514.  
  2515.     mov   [hd_error],0
  2516.  
  2517.     cmp   [hd_setup],1          ; do not mark error for setup request
  2518.     je    buf_wait_ok
  2519.  
  2520.     test  al,1                  ; previous command ended up with an error
  2521.     jz    buf_wait_ok
  2522.     mov   [hd_error],1
  2523.  
  2524.   buf_wait_ok:
  2525.  
  2526.     pop   edx eax
  2527.     ret
  2528.  
  2529.  
  2530.  
  2531. read_hd_file:
  2532. ;-----------------------------------------------------------------
  2533. ;
  2534. ; Converting old reading function for hd-application start.
  2535. ;
  2536. ; IN:
  2537. ;
  2538. ; eax - pointer to file (0 = read only first sector of drive: eg 'label')
  2539. ; ebx - file lenght
  2540. ; ecx - start 512 byte block number
  2541. ; edx - number of blocks to read
  2542. ; esi - pointer to return/work area (atleast 20 000 bytes)
  2543. ;
  2544. ; For new read function
  2545. ;
  2546. ; EAX   (PAR0)      pointer to file-name
  2547. ; ECX   (PAR1)      pointer to buffer
  2548. ; EBX   (PAR2)   vt file blocks to read
  2549. ; EDX   (PAR3)      pointer to path
  2550. ; ESI            vt first 512 block to read
  2551. ; EDI               if 0 - return root
  2552. ;--------------------------------------------------------------------------
  2553.  
  2554.     push  ecx esi edi
  2555.     mov   esi,eax
  2556.     mov   edi,startpath
  2557.     mov   ecx,250
  2558.     cld
  2559.     rep   movsb
  2560.     pop   edi esi ecx
  2561.  
  2562.     mov   eax,startpath
  2563.     mov   [eax+ebx-12],byte 0
  2564.  
  2565.     push  eax ebx ecx edx esi
  2566.  
  2567.     pop   ecx ; pointer to buffer
  2568.     add   ecx,1024
  2569.     pop   ebx ; number of blocks to read
  2570.     pop   esi ; first block to read
  2571.     dec   esi
  2572.     pop   eax ; file length
  2573.     pop   edx ; pointer to path
  2574.  
  2575.     mov   edi,12
  2576.     lea   eax,[eax+edx-12+1]
  2577.     call  file_read
  2578.  
  2579.     ret
  2580.  
  2581. ; \begin{diamond}
  2582. hd_find_lfn:
  2583. ; in: esi->name
  2584. ; out: CF=1 - file not found
  2585. ;      else CF=0 and edi->direntry
  2586.         pusha
  2587.         sub     esp, 262*2      ; allocate space for LFN
  2588.         mov     ebp, esp
  2589.         mov     eax, [ROOT_CLUSTER]     ; start from root
  2590. .mainloop:
  2591. .new_cluster:
  2592.         mov     [cluster_tmp], eax
  2593.         mov     [fat16_root], 0
  2594.         cmp     eax, [LAST_CLUSTER]
  2595.         ja      .notfound
  2596.         cmp     eax, 2
  2597.         jae     .data_cluster
  2598.         cmp     [fat_type], 16
  2599.         jnz     .notfound
  2600.         mov     eax, [ROOT_START]
  2601.         mov     ecx, [ROOT_SECTORS]
  2602.         mov     [fat16_root], 1
  2603.         jmp     .new_sector
  2604. .data_cluster:
  2605.         dec     eax
  2606.         dec     eax
  2607.         mov     ecx, [SECTORS_PER_CLUSTER]
  2608.         mul     ecx
  2609.         add     eax, [DATA_START]
  2610. .new_sector:
  2611.         mov     ebx, buffer
  2612.         call    hd_read
  2613.         mov     edi, ebx
  2614.         add     ebx, 512
  2615.         push    eax
  2616. .l1:
  2617.         call    fat_get_name
  2618.         jc      .l2
  2619.         call    fat_compare_name
  2620.         jz      .found
  2621. .l2:
  2622.         add     edi, 0x20
  2623.         cmp     edi, ebx
  2624.         jb      .l1
  2625.         pop     eax
  2626.         inc     eax
  2627.         loop    .new_sector
  2628.         cmp     [fat16_root], 0
  2629.         jnz     .notfound
  2630.         mov     eax, [cluster_tmp]
  2631.         call    get_FAT
  2632.         cmp     eax, 2
  2633.         jb      .notfound
  2634.         cmp     eax, [fatRESERVED]
  2635.         jb      .new_cluster
  2636. .notfound:
  2637.         add     esp, 262*2
  2638.         popa
  2639.         stc
  2640.         ret
  2641. .found:
  2642.         pop     eax
  2643. ; if this is LFN entry, advance to true entry
  2644.         cmp     byte [edi+11], 0xF
  2645.         jnz     .entryfound
  2646.         add     edi, 0x20
  2647.         cmp     edi, ebx
  2648.         jb      .entryfound
  2649.         inc     eax
  2650.         dec     ecx
  2651.         jnz     .read_entry
  2652.         cmp     [fat16_root], 0
  2653.         jnz     .notfound
  2654.         mov     eax, [cluster_tmp]
  2655.         call    get_FAT
  2656.         cmp     eax, 2
  2657.         jb      .notfound
  2658.         cmp     eax, [fatRESERVED]
  2659.         jae     .notfound
  2660.         dec     eax
  2661.         dec     eax
  2662.         mul     [SECTORS_PER_CLUSTER]
  2663.         add     eax, [DATA_START]
  2664. .read_entry:
  2665.         mov     ebx, [buffer]
  2666.         call    hd_read
  2667.         mov     edi, ebx
  2668. .entryfound:
  2669.         cmp     byte [esi], 0
  2670.         jz      .done
  2671.         test    byte [edi+11], 10h      ; is a directory?
  2672.         jz      .notfound
  2673.         mov     eax, [edi+20-2]
  2674.         mov     ax, [edi+26]
  2675.         jmp     .mainloop
  2676. .done:
  2677.         add     esp, 262*2+4    ; CF=0
  2678.         push    edi
  2679.         popad
  2680.         ret
  2681.  
  2682. ;----------------------------------------------------------------
  2683. ;
  2684. ;  fs_HdRead - LFN variant for reading hard disk
  2685. ;
  2686. ;  esi  points to filename
  2687. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  2688. ;       may be ebx=0 - start from first byte
  2689. ;  ecx  number of bytes to read, 0+
  2690. ;  edx  mem location to return data
  2691. ;
  2692. ;  ret ebx = size or 0xffffffff file not found
  2693. ;      eax = 0 ok read or other = errormsg
  2694. ;
  2695. ;--------------------------------------------------------------
  2696. fs_HdRead:
  2697.         cmp     [fat_type], 0
  2698.         jnz     @f
  2699.         or      ebx, -1
  2700.         mov     eax, ERROR_UNKNOWN_FS
  2701.         ret
  2702. @@:
  2703.         push    edi
  2704.         cmp     byte [esi], 0
  2705.         jnz     @f
  2706. .noaccess:
  2707.         pop     edi
  2708.         or      ebx, -1
  2709.         mov     eax, ERROR_ACCESS_DENIED
  2710.         ret
  2711. @@:
  2712.         call    hd_find_lfn
  2713.         jnc     .found
  2714.         pop     edi
  2715.         or      ebx, -1
  2716.         mov     eax, ERROR_FILE_NOT_FOUND
  2717.         ret
  2718. .found:
  2719.         test    byte [edi+11], 0x10     ; do not allow read directories
  2720.         jnz     .noaccess
  2721.         test    ebx, ebx
  2722.         jz      .l1
  2723.         cmp     dword [ebx+4], 0
  2724.         jz      @f
  2725.         mov     ebx, [edi+28]
  2726. .reteof:
  2727.         mov     eax, 6
  2728.         pop     edi
  2729.         ret
  2730. @@:
  2731.         mov     ebx, [ebx]
  2732. .l1:
  2733.         push    dword [edi+28]          ; file size
  2734.         mov     eax, [edi+20-2]
  2735.         mov     ax, [edi+26]
  2736.         push    ecx edx
  2737.         push    dword [edi+28]
  2738. ; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
  2739. .new_cluster:
  2740.         jecxz   .new_sector
  2741.         test    eax, eax
  2742.         jz      .eof
  2743.         cmp     eax, [fatRESERVED]
  2744.         jae     .eof
  2745.         mov     [cluster_tmp], eax
  2746.         dec     eax
  2747.         dec     eax
  2748.         mov     edi, [SECTORS_PER_CLUSTER]
  2749.         imul    eax, edi
  2750.         add     eax, [DATA_START]
  2751. .new_sector:
  2752.         test    ecx, ecx
  2753.         jz      .done
  2754.         sub     ebx, 512
  2755.         jae     .skip
  2756.         add     ebx, 512
  2757.         jnz     .force_buf
  2758.         cmp     ecx, 512
  2759.         jb      .force_buf
  2760.         cmp     dword [esp], 512
  2761.         jb      .force_buf
  2762. ; we may read directly to given buffer
  2763.         push    ebx
  2764.         mov     ebx, edx
  2765.         call    hd_read
  2766.         pop     ebx
  2767.         add     edx, 512
  2768.         sub     ecx, 512
  2769.         sub     dword [esp], 512
  2770.         jmp     .skip
  2771. .force_buf:
  2772. ; we must read sector to temporary buffer and then copy it to destination
  2773.         push    eax ebx
  2774.         mov     ebx, buffer
  2775.         call    hd_read
  2776.         mov     eax, ebx
  2777.         pop     ebx
  2778.         add     eax, ebx
  2779.         push    ecx
  2780.         add     ecx, ebx
  2781.         cmp     ecx, 512
  2782.         jbe     @f
  2783.         mov     ecx, 512
  2784. @@:
  2785.         sub     ecx, ebx
  2786.         cmp     ecx, [esp+8]
  2787.         jbe     @f
  2788.         mov     ecx, [esp+8]
  2789. @@:
  2790.         mov     ebx, edx
  2791.         call    memmove
  2792.         add     edx, ecx
  2793.         sub     [esp], ecx
  2794.         sub     [esp+8], ecx
  2795.         pop     ecx
  2796.         pop     eax
  2797.         xor     ebx, ebx
  2798.         cmp     [esp], ebx
  2799.         jnz     .skip
  2800.         jecxz   .done
  2801.         jmp     .eof
  2802. .skip:
  2803.         inc     eax
  2804.         dec     edi
  2805.         jnz     .new_sector
  2806.         mov     eax, [cluster_tmp]
  2807.         call    get_FAT
  2808.         jmp     .new_cluster
  2809. .done:
  2810.         pop     ebx edx ecx ebx edi
  2811.         xor     eax, eax
  2812.         ret
  2813. .eof:
  2814.         pop     ebx edx ecx ebx
  2815.         jmp     .reteof
  2816. ; \end{diamond}