Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  FAT32.INC                                                      ;;
  7. ;;                                                                 ;;
  8. ;;  FAT16/32 functions for KolibriOS                               ;;
  9. ;;                                                                 ;;
  10. ;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
  11. ;;                                                                 ;;
  12. ;;  See file COPYING for details                                   ;;
  13. ;;  04.02.2007 LFN create folder - diamond                         ;;
  14. ;;  08.10.2006 LFN delete file/folder - diamond                    ;;
  15. ;;  20.08.2006 LFN set file size (truncate/extend) - diamond       ;;
  16. ;;  17.08.2006 LFN write/append to file - diamond                  ;;
  17. ;;  23.06.2006 LFN start application - diamond                     ;;
  18. ;;  15.06.2006 LFN get/set file/folder info - diamond              ;;
  19. ;;  27.05.2006 LFN create/rewrite file - diamond                   ;;
  20. ;;  04.05.2006 LFN read folder - diamond                           ;;
  21. ;;  29.04.2006 Elimination of hangup after the                     ;;
  22. ;;             expiration hd_wait_timeout -  Mario79               ;;
  23. ;;  23.04.2006 LFN read file - diamond                             ;;
  24. ;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
  25. ;;             to MBR, see file part_set.inc - Mario79             ;;
  26. ;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
  27. ;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
  28. ;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
  29. ;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
  30. ;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
  31. ;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
  32. ;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
  33. ;;  08.11.2004 rename - ATV                                        ;;
  34. ;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
  35. ;;  20.10.2004 Makedir/Removedir - ATV                             ;;
  36. ;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
  37. ;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
  38. ;;  24.5.2004  Write back buffer for File_write -VT                ;;
  39. ;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
  40. ;;  30.3.2004  Error parameters at function return - VT            ;;
  41. ;;  01.5.2002  Bugfix in device write - VT                         ;;
  42. ;;  20.5.2002  Hd status check - VT                                ;;
  43. ;;  29.6.2002  Improved fat32 verification - VT                    ;;
  44. ;;                                                                 ;;
  45. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  46.  
  47. $Revision: 3725 $
  48.  
  49.  
  50. cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
  51.  
  52. PUSHAD_EAX equ [esp+28]
  53. PUSHAD_ECX equ [esp+24]
  54. PUSHAD_EDX equ [esp+20]
  55. PUSHAD_EBX equ [esp+16]
  56. PUSHAD_EBP equ [esp+8]
  57. PUSHAD_ESI equ [esp+4]
  58. PUSHAD_EDI equ [esp+0]
  59.  
  60. ; Internal data for every FAT partition.
  61. struct FAT
  62. p       PARTITION       ; must be the first item
  63. fs_type              db ?
  64. fat16_root           db 0       ; flag for fat16 rootdir
  65. fat_change           db 0       ; 1=fat has changed
  66.                      db ?       ; alignment
  67. Lock                 MUTEX ?    ; currently operations with one partition
  68.                                  ; can not be executed in parallel since the
  69.                                  ; legacy code is not ready; this mutex guards
  70.                                  ; all operations
  71. SECTORS_PER_FAT      dd 0x1f3a
  72. NUMBER_OF_FATS       dd 0x2
  73. SECTORS_PER_CLUSTER  dd 0x8
  74. BYTES_PER_SECTOR     dd 0x200   ; Note: if BPS <> 512 need lots of changes
  75. ROOT_CLUSTER         dd 2       ; first rootdir cluster
  76. FAT_START            dd 0       ; start of fat table
  77. ROOT_START           dd 0       ; start of rootdir (only fat16)
  78. ROOT_SECTORS         dd 0       ; count of rootdir sectors (only fat16)
  79. DATA_START           dd 0       ; start of data area (=first cluster 2)
  80. LAST_CLUSTER         dd 0       ; last availabe cluster
  81. ADR_FSINFO           dd 0       ; used only by fat32
  82.  
  83. fatRESERVED          dd 0x0FFFFFF6
  84. fatBAD               dd 0x0FFFFFF7
  85. fatEND               dd 0x0FFFFFF8
  86. fatMASK              dd 0x0FFFFFFF
  87.  
  88. fatStartScan         dd 2
  89.  
  90. cluster_tmp          dd 0       ; used by analyze_directory
  91.                                 ; and analyze_directory_to_write
  92.  
  93. longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
  94. longname_sec2        dd 0       ; directory sectors for delete long filename
  95.  
  96. fat_in_cache         dd -1
  97.  
  98. fat_cache            rb 512
  99. buffer               rb 512
  100. fsinfo_buffer        rb 512
  101. ends
  102.  
  103. uglobal
  104. align 4
  105. partition_count      dd 0       ; partitions found by set_FAT32_variables
  106.  
  107. hd_error             dd 0       ; set by wait_for_sector_buffer
  108. hd_setup             dd 0
  109. hd_wait_timeout      dd 0
  110.  
  111. cache_search_start   dd 0       ; used by find_empty_slot
  112. endg
  113.  
  114. uglobal
  115. align 4
  116.  Sector512:                      ; label for dev_hdcd.inc
  117.   buffer:
  118.                        times 512 db 0
  119. endg
  120.  
  121. iglobal
  122. align 4
  123. fat_user_functions:
  124.         dd      (fat_user_functions_end - fat_user_functions - 4) / 4
  125.         dd      fat_Read
  126.         dd      fat_ReadFolder
  127.         dd      fat_Rewrite
  128.         dd      fat_Write
  129.         dd      fat_SetFileEnd
  130.         dd      fat_GetFileInfo
  131.         dd      fat_SetFileInfo
  132.         dd      0
  133.         dd      fat_Delete
  134.         dd      fat_CreateFolder
  135. fat_user_functions_end:
  136. endg
  137.  
  138. ; these labels are located before the main function to make
  139. ; most of jumps to these be short
  140. fat_create_partition.free_return0:
  141.         push    ebx
  142.         mov     eax, ebp
  143.         call    free
  144.         pop     ebx
  145.         pop     ebp
  146. fat_create_partition.return0:
  147.         xor     eax, eax
  148.         ret
  149. fat_create_partition:
  150. ; bootsector must have been successfully read
  151.         cmp     dword [esp+4], 1
  152.         jnz     .return0
  153. ; bootsector signature must be correct
  154.         cmp     word [ebx+0x1fe], 0xaa55
  155.         jnz     .return0
  156. ; sectors per cluster must be nonzero
  157.         cmp     byte [ebx+0xd], 0
  158.         jz      .return0
  159. ; bytes per sector must be 0x200
  160.         cmp     word [ebx+0xb], 0x200
  161.         jnz     .return0
  162. ; number of fats must be nonzero
  163.         cmp     byte [ebx+0x10], 0
  164.         jz      .return0
  165. ; The only reason to be invalid partition now is FAT12. Since the test for
  166. ; FAT size requires knowledge of some calculated values, which are also used
  167. ; in the normal operation, let's hope for the best and allocate data now; if
  168. ; it will prove wrong, just deallocate it.
  169.         movi    eax, sizeof.FAT
  170.         call    malloc
  171.         test    eax, eax
  172.         jz      .return0
  173.         mov     ecx, [ebp+8]
  174.         mov     dword [eax+FAT.p.FirstSector], ecx
  175.         mov     ecx, [ebp+12]
  176.         mov     dword [eax+FAT.p.FirstSector+4], ecx
  177.         mov     ecx, [ebp+16]
  178.         mov     dword [eax+FAT.p.Length], ecx
  179.         mov     ecx, [ebp+20]
  180.         mov     dword [eax+FAT.p.Length+4], ecx
  181.         mov     [eax+FAT.p.Disk], esi
  182.         mov     [eax+FAT.p.FSUserFunctions], fat_user_functions
  183.         or      [eax+FAT.fat_in_cache], -1
  184.         mov     [eax+FAT.fat_change], 0
  185.         push    ebp
  186.         mov     ebp, eax
  187.  
  188.         lea     ecx, [ebp+FAT.Lock]
  189.         call    mutex_init
  190.  
  191.         movzx   eax, word [ebx+0xe]     ; sectors reserved
  192.         mov     [ebp+FAT.FAT_START], eax
  193.  
  194.         movzx   eax, byte [ebx+0xd]     ; sectors per cluster
  195.         mov     [ebp+FAT.SECTORS_PER_CLUSTER], eax
  196.  
  197.         movzx   ecx, word [ebx+0xb]     ; bytes per sector
  198.         mov     [ebp+FAT.BYTES_PER_SECTOR], ecx
  199.  
  200.         movzx   eax, word [ebx+0x11]    ; count of rootdir entries (=0 fat32)
  201.         shl     eax, 5                  ; mul 32
  202.         dec     ecx
  203.         add     eax, ecx                ; round up if not equal count
  204.         inc     ecx                     ; bytes per sector
  205.         xor     edx, edx
  206.         div     ecx
  207.         mov     [ebp+FAT.ROOT_SECTORS], eax     ; count of rootdir sectors
  208.  
  209.         movzx   eax, word [ebx+0x16]    ; sectors per fat <65536
  210.         test    eax, eax
  211.         jnz     @f
  212.         mov     eax, [ebx+0x24]         ; sectors per fat
  213. @@:
  214.         mov     [ebp+FAT.SECTORS_PER_FAT], eax
  215.  
  216.         movzx   eax, byte [ebx+0x10]    ; number of fats
  217.         mov     [ebp+FAT.NUMBER_OF_FATS], eax
  218.         imul    eax, [ebp+FAT.SECTORS_PER_FAT]
  219.         add     eax, [ebp+FAT.FAT_START]
  220.         mov     [ebp+FAT.ROOT_START], eax       ; rootdir = fat_start + fat_size * fat_count
  221.         add     eax, [ebp+FAT.ROOT_SECTORS]     ; rootdir sectors should be 0 on fat32
  222.         mov     [ebp+FAT.DATA_START], eax       ; data area = rootdir + rootdir_size
  223.  
  224.         movzx   eax, word [ebx+0x13]    ; total sector count <65536
  225.         test    eax, eax
  226.         jnz     @f
  227.         mov     eax, [ebx+0x20]         ; total sector count
  228. @@:
  229.         mov     dword [ebp+FAT.p.Length], eax
  230.         and     dword [ebp+FAT.p.Length+4], 0
  231.         sub     eax, [ebp+FAT.DATA_START]       ; eax = count of data sectors
  232.         xor     edx, edx
  233.         div     [ebp+FAT.SECTORS_PER_CLUSTER]
  234.         inc     eax
  235.         mov     [ebp+FAT.LAST_CLUSTER], eax
  236.         dec     eax                     ; cluster count
  237.         mov     [ebp+FAT.fatStartScan], 2
  238.  
  239.         ; limits by Microsoft Hardware White Paper v1.03
  240.         cmp     eax, 4085               ; 0xff5
  241.         jb      .free_return0           ; fat12 not supported
  242.         cmp     eax, 65525              ; 0xfff5
  243.         jb      .fat16
  244. .fat32:
  245.         mov     eax, [ebx+0x2c]         ; rootdir cluster
  246.         mov     [ebp+FAT.ROOT_CLUSTER], eax
  247.         movzx   eax, word [ebx+0x30]
  248.         mov     [ebp+FAT.ADR_FSINFO], eax
  249.         push    ebx
  250.         add     ebx, 512
  251.         call    fs_read32_sys
  252.         test    eax, eax
  253.         jnz     @f
  254.         mov     eax, [ebx+0x1ec]
  255.         cmp     eax, -1
  256.         jz      @f
  257.         mov     [ebp+FAT.fatStartScan], eax
  258. @@:
  259.         pop     ebx
  260.         mov     [ebp+FAT.fatRESERVED], 0x0FFFFFF6
  261.         mov     [ebp+FAT.fatBAD], 0x0FFFFFF7
  262.         mov     [ebp+FAT.fatEND], 0x0FFFFFF8
  263.         mov     [ebp+FAT.fatMASK], 0x0FFFFFFF
  264.         mov     al, 32
  265.         mov     [fs_type], al
  266.         mov     [ebp+FAT.fs_type], al
  267.         mov     eax, ebp
  268.         pop     ebp
  269.         ret
  270. .fat16:
  271.         and     [ebp+FAT.ROOT_CLUSTER], 0
  272.         mov     [ebp+FAT.fatRESERVED], 0x0000FFF6
  273.         mov     [ebp+FAT.fatBAD], 0x0000FFF7
  274.         mov     [ebp+FAT.fatEND], 0x0000FFF8
  275.         mov     [ebp+FAT.fatMASK], 0x0000FFFF
  276.         mov     al, 16
  277.         mov     [fs_type], al
  278.         mov     [ebp+FAT.fs_type], al
  279.         mov     eax, ebp
  280.         pop     ebp
  281.         ret
  282.  
  283. set_FAT:
  284. ;--------------------------------
  285. ; input  : EAX = cluster
  286. ;          EDX = value to save
  287. ;          EBP = pointer to FAT structure
  288. ; output : EDX = old value
  289. ;--------------------------------
  290. ; out: CF set <=> error
  291.         push    eax ebx esi
  292.  
  293.         cmp     eax, 2
  294.         jb      sfc_error
  295.         cmp     eax, [ebp+FAT.LAST_CLUSTER]
  296.         ja      sfc_error
  297.         cmp     [ebp+FAT.fs_type], 16
  298.         je      sfc_1
  299.         add     eax, eax
  300.   sfc_1:
  301.         add     eax, eax
  302.         mov     esi, 511
  303.         and     esi, eax        ; esi = position in fat sector
  304.         shr     eax, 9          ; eax = fat sector
  305.         add     eax, [ebp+FAT.FAT_START]
  306.         lea     ebx, [ebp+FAT.fat_cache]
  307.  
  308.         cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
  309.         je      sfc_in_cache    ; yes
  310.  
  311.         cmp     [ebp+FAT.fat_change], 0; is fat changed?
  312.         je      sfc_no_change   ; no
  313.         call    write_fat_sector; yes. write it into disk
  314.         jc      sfc_error
  315.  
  316.   sfc_no_change:
  317.         mov     [ebp+FAT.fat_in_cache], eax; save fat sector
  318.         call    fs_read32_sys
  319.         test    eax, eax
  320.         jne     sfc_error
  321.  
  322.  
  323.   sfc_in_cache:
  324.         cmp     [ebp+FAT.fs_type], 16
  325.         jne     sfc_test32
  326.  
  327.   sfc_set16:
  328.         xchg    [ebx+esi], dx   ; save new value and get old value
  329.         jmp     sfc_write
  330.  
  331.   sfc_test32:
  332.         mov     eax, [ebp+FAT.fatMASK]
  333.  
  334.   sfc_set32:
  335.         and     edx, eax
  336.         xor     eax, -1         ; mask for high bits
  337.         and     eax, [ebx+esi]  ; get high 4 bits
  338.         or      eax, edx
  339.         mov     edx, [ebx+esi]  ; get old value
  340.         mov     [ebx+esi], eax  ; save new value
  341.  
  342.   sfc_write:
  343.         mov     [ebp+FAT.fat_change], 1; fat has changed
  344.  
  345.   sfc_nonzero:
  346.         and     edx, [ebp+FAT.fatMASK]
  347.  
  348.   sfc_return:
  349.         pop     esi ebx eax
  350.         ret
  351.   sfc_error:
  352.         stc
  353.         jmp     sfc_return
  354.  
  355.  
  356. get_FAT:
  357. ;--------------------------------
  358. ; input  : EAX = cluster
  359. ;          EBP = pointer to FAT structure
  360. ; output : EAX = next cluster
  361. ;--------------------------------
  362. ; out: CF set <=> error
  363.         push    ebx esi
  364.  
  365.         cmp     [ebp+FAT.fs_type], 16
  366.         je      gfc_1
  367.         add     eax, eax
  368.   gfc_1:
  369.         add     eax, eax
  370.         mov     esi, 511
  371.         and     esi, eax        ; esi = position in fat sector
  372.         shr     eax, 9          ; eax = fat sector
  373.         add     eax, [ebp+FAT.FAT_START]
  374.         lea     ebx, [ebp+FAT.fat_cache]
  375.  
  376.         cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
  377.         je      gfc_in_cache
  378.  
  379.         cmp     [ebp+FAT.fat_change], 0; is fat changed?
  380.         je      gfc_no_change   ; no
  381.         call    write_fat_sector; yes. write it into disk
  382.         jc      hd_error_01
  383.  
  384.   gfc_no_change:
  385.         mov     [ebp+FAT.fat_in_cache], eax
  386.         call    fs_read32_sys
  387.         test    eax, eax
  388.         jne     hd_error_01
  389.  
  390.   gfc_in_cache:
  391.         mov     eax, [ebx+esi]
  392.         and     eax, [ebp+FAT.fatMASK]
  393.   gfc_return:
  394.         pop     esi ebx
  395.         ret
  396.  hd_error_01:
  397.         stc
  398.         jmp     gfc_return
  399.  
  400.  
  401. get_free_FAT:
  402. ;-----------------------------------------------------------
  403. ; output : if CARRY=0 EAX = # first cluster found free
  404. ;          if CARRY=1 disk full
  405. ; Note   : for more speed need to use fat_cache directly
  406. ;-----------------------------------------------------------
  407.         push    ecx
  408.         mov     ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
  409.         sub     ecx, 2
  410.         mov     eax, [ebp+FAT.fatStartScan]
  411.         cmp     eax, 2
  412.         jb      gff_reset
  413.  
  414.   gff_test:
  415.         cmp     eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
  416.         jbe     gff_in_range
  417.   gff_reset:
  418.         mov     eax, 2
  419.  
  420.   gff_in_range:
  421.         push    eax
  422.         call    get_FAT         ; get cluster state
  423.         jc      gff_not_found_1
  424.  
  425.         test    eax, eax        ; is it free?
  426.         pop     eax
  427.         je      gff_found       ; yes
  428.         inc     eax             ; next cluster
  429.         dec     ecx             ; is all checked?
  430.         jns     gff_test        ; no
  431.  
  432.   gff_not_found:
  433.         pop     ecx             ; yes. disk is full
  434.         stc
  435.         ret
  436.  
  437.   gff_not_found_1:
  438.         pop     eax
  439.         jmp     gff_not_found
  440.  
  441.   gff_found:
  442.         lea     ecx, [eax+1]
  443.         mov     [ebp+FAT.fatStartScan], ecx
  444.         pop     ecx
  445.         clc
  446.         ret
  447.  
  448.  
  449. write_fat_sector:
  450. ;-----------------------------------------------------------
  451. ; write changed fat to disk
  452. ;-----------------------------------------------------------
  453.         push    eax ebx ecx
  454.  
  455.         mov     [ebp+FAT.fat_change], 0
  456.         mov     eax, [ebp+FAT.fat_in_cache]
  457.         cmp     eax, -1
  458.         jz      write_fat_not_used
  459.         lea     ebx, [ebp+FAT.fat_cache]
  460.         mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
  461.  
  462.   write_next_fat:
  463.         push    eax
  464.         call    fs_write32_sys
  465.         test    eax, eax
  466.         pop     eax
  467.         jnz     write_fat_not_used
  468.  
  469.         add     eax, [ebp+FAT.SECTORS_PER_FAT]
  470.         dec     ecx
  471.         jnz     write_next_fat
  472.  
  473.   write_fat_not_used:
  474.         pop     ecx ebx eax
  475.         ret
  476.  
  477.  
  478.  
  479.  
  480.  
  481. bcd2bin:
  482. ;----------------------------------
  483. ; input  : AL=BCD number (eg. 0x11)
  484. ; output : AH=0
  485. ;          AL=decimal number (eg. 11)
  486. ;----------------------------------
  487.         xor     ah, ah
  488.         shl     ax, 4
  489.         shr     al, 4
  490.         aad
  491.         ret
  492.  
  493.  
  494. get_date_for_file:
  495. ;-----------------------------------------------------
  496. ; Get date from CMOS and pack day,month,year in AX
  497. ; DATE   bits  0..4   : day of month 0..31
  498. ;              5..8   : month of year 1..12
  499. ;              9..15  : count of years from 1980
  500. ;-----------------------------------------------------
  501.         mov     al, 0x7 ;day
  502.         out     0x70, al
  503.         in      al, 0x71
  504.         call    bcd2bin
  505.         ror     eax, 5
  506.  
  507.         mov     al, 0x8 ;month
  508.         out     0x70, al
  509.         in      al, 0x71
  510.         call    bcd2bin
  511.         ror     eax, 4
  512.  
  513.         mov     al, 0x9 ;year
  514.         out     0x70, al
  515.         in      al, 0x71
  516.         call    bcd2bin
  517.         add     ax, 20  ;because CMOS return only the two last
  518.                         ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
  519.         rol     eax, 9  ;need the difference with 1980 (eg. 2001-1980)
  520.         ret
  521.  
  522.  
  523. get_time_for_file:
  524. ;-----------------------------------------------------
  525. ; Get time from CMOS and pack hour,minute,second in AX
  526. ; TIME   bits  0..4   : second (the low bit is lost)
  527. ;              5..10  : minute 0..59
  528. ;              11..15 : hour 0..23
  529. ;-----------------------------------------------------
  530.         mov     al, 0x0 ;second
  531.         out     0x70, al
  532.         in      al, 0x71
  533.         call    bcd2bin
  534.         ror     eax, 6
  535.  
  536.         mov     al, 0x2 ;minute
  537.         out     0x70, al
  538.         in      al, 0x71
  539.         call    bcd2bin
  540.         ror     eax, 6
  541.  
  542.         mov     al, 0x4 ;hour
  543.         out     0x70, al
  544.         in      al, 0x71
  545.         call    bcd2bin
  546.         rol     eax, 11
  547.         ret
  548.  
  549.  
  550. set_current_time_for_entry:
  551. ;-----------------------------------------------------
  552. ; Set current time/date for file entry
  553. ; input  : ebx = file entry pointer
  554. ;-----------------------------------------------------
  555.         push    eax
  556.         call    get_time_for_file; update files date/time
  557.         mov     [ebx+22], ax
  558.         call    get_date_for_file
  559.         mov     [ebx+24], ax
  560.         pop     eax
  561.         ret
  562.  
  563.  
  564.  
  565. add_disk_free_space:
  566. ;-----------------------------------------------------
  567. ; input  : ecx = cluster count
  568. ; Note   : negative = remove clusters from free space
  569. ;          positive = add clusters to free space
  570. ;-----------------------------------------------------
  571.         test    ecx, ecx        ; no change
  572.         je      add_dfs_no
  573.         cmp     [ebp+FAT.fs_type], 32  ; free disk space only used by fat32
  574.         jne     add_dfs_no
  575.  
  576.         push    eax ebx
  577.         mov     eax, [ebp+FAT.ADR_FSINFO]
  578.         lea     ebx, [ebp+FAT.fsinfo_buffer]
  579.         call    fs_read32_sys
  580.         test    eax, eax
  581.         jnz     add_not_fs
  582.  
  583.         cmp     dword [ebx+0x1fc], 0xaa550000; check sector id
  584.         jne     add_not_fs
  585.  
  586.         add     [ebx+0x1e8], ecx
  587.         push    [ebp+FAT.fatStartScan]
  588.         pop     dword [ebx+0x1ec]
  589.         mov     eax, [ebp+FAT.ADR_FSINFO]
  590.         call    fs_write32_sys
  591. ;    jc    add_not_fs
  592.  
  593.   add_not_fs:
  594.         pop     ebx eax
  595.  
  596.   add_dfs_no:
  597.         ret
  598.  
  599.  
  600.  
  601. clear_cluster_chain:
  602. ;-----------------------------------------------------
  603. ; input  : eax = first cluster
  604. ;-----------------------------------------------------
  605.         push    eax ecx edx
  606.         xor     ecx, ecx        ; cluster count
  607.  
  608.   clean_new_chain:
  609.         cmp     eax, [ebp+FAT.LAST_CLUSTER]; end of file
  610.         ja      delete_OK
  611.         cmp     eax, 2          ; unfinished fat chain or zero length file
  612.         jb      delete_OK
  613.         cmp     eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
  614.         jz      delete_OK
  615.  
  616.         xor     edx, edx
  617.         call    set_FAT         ; clear fat entry
  618.         jc      access_denied_01
  619.  
  620.         inc     ecx             ; update cluster count
  621.         mov     eax, edx        ; old cluster
  622.         jmp     clean_new_chain
  623.  
  624.   delete_OK:
  625.         call    add_disk_free_space; add clusters to free disk space
  626.         clc
  627.   access_denied_01:
  628.         pop     edx ecx eax
  629.         ret
  630.  
  631.  
  632. if 0
  633. get_hd_info:
  634. ;-----------------------------------------------------------
  635. ; output : eax = 0 - ok
  636. ;                3 - unknown FS
  637. ;               10 - access denied
  638. ;          edx = cluster size in bytes
  639. ;          ebx = total clusters on disk
  640. ;          ecx = free clusters on disk
  641. ;-----------------------------------------------------------
  642.         cmp     [ebp+FAT.fs_type], 16
  643.         jz      info_fat_ok
  644.         cmp     [ebp+FAT.fs_type], 32
  645.         jz      info_fat_ok
  646.         xor     edx, edx
  647.         xor     ebx, ebx
  648.         xor     ecx, ecx
  649.         mov     eax, ERROR_UNKNOWN_FS
  650.         ret
  651.  
  652.   info_fat_ok:
  653. ;    call  reserve_hd1
  654.  
  655.         xor     ecx, ecx        ; count of free clusters
  656.         mov     eax, 2
  657.         mov     ebx, [ebp+FAT.LAST_CLUSTER]
  658.  
  659.   info_cluster:
  660.         push    eax
  661.         call    get_FAT         ; get cluster info
  662.         jc      info_access_denied
  663.  
  664.         test    eax, eax        ; is it free?
  665.         jnz     info_used       ; no
  666.         inc     ecx
  667.  
  668.   info_used:
  669.         pop     eax
  670.         inc     eax
  671.         cmp     eax, ebx        ; is above last cluster?
  672.         jbe     info_cluster    ; no. test next cluster
  673.  
  674.         dec     ebx             ; cluster count
  675.         imul    edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
  676.         xor     eax, eax
  677.         ret
  678.  
  679.   info_access_denied:
  680.         add     esp, 4
  681.         xor     edx, edx
  682.         xor     ebx, ebx
  683.         xor     ecx, ecx
  684.         mov     eax, ERROR_ACCESS_DENIED
  685.         ret
  686. end if
  687.  
  688. update_disk:
  689. ;-----------------------------------------------------------
  690. ; write changed fat and cache to disk
  691. ;-----------------------------------------------------------
  692.         cmp     [ebp+FAT.fat_change], 0 ; is fat changed?
  693.         je      upd_no_change
  694.  
  695.         call    write_fat_sector
  696.         jc      update_disk_acces_denied
  697.  
  698.   upd_no_change:
  699.  
  700.         push    esi
  701.         mov     esi, [ebp+PARTITION.Disk]
  702.         call    disk_sync
  703.         pop     esi
  704.   update_disk_acces_denied:
  705.         ret
  706.  
  707. fat_lock:
  708.         lea     ecx, [ebp+FAT.Lock]
  709.         jmp     mutex_lock
  710. fat_unlock:
  711.         lea     ecx, [ebp+FAT.Lock]
  712.         jmp     mutex_unlock
  713.  
  714. ; \begin{diamond}
  715. hd_find_lfn:
  716. ; in: ebp -> FAT structure
  717. ; in: esi+[esp+4] -> name
  718. ; out: CF=1 - file not found, eax=error code
  719. ;      else CF=0 and edi->direntry, eax=sector
  720. ; destroys eax
  721.         push    esi edi
  722.         push    0
  723.         push    0
  724.         push    fat16_root_first
  725.         push    fat16_root_next
  726.         mov     eax, [ebp+FAT.ROOT_CLUSTER]
  727.         cmp     [ebp+FAT.fs_type], 32
  728.         jz      .fat32
  729. .loop:
  730.         call    fat_find_lfn
  731.         jc      .notfound
  732.         cmp     byte [esi], 0
  733.         jz      .found
  734. .continue:
  735.         test    byte [edi+11], 10h
  736.         jz      .notfound
  737.         and     dword [esp+12], 0
  738.         mov     eax, [edi+20-2]
  739.         mov     ax, [edi+26]    ; cluster
  740. .fat32:
  741.         mov     [esp+8], eax
  742.         mov     dword [esp+4], fat_notroot_first
  743.         mov     dword [esp], fat_notroot_next
  744.         jmp     .loop
  745. .notfound:
  746.         add     esp, 16
  747.         pop     edi esi
  748.         stc
  749.         ret     4
  750. .found:
  751.         lea     eax, [esp+4+24]
  752.         cmp     dword [eax], 0
  753.         jz      @f
  754.         mov     esi, [eax]
  755.         and     dword [eax], 0
  756.         jmp     .continue
  757. @@:
  758.         lea     eax, [esp+8]
  759.         cmp     dword [eax], 0
  760.         jz      .root
  761.         call    fat_get_sector
  762.         jmp     .cmn
  763. .root:
  764.         mov     eax, [eax+4]
  765.         add     eax, [ebp+FAT.ROOT_START]
  766. .cmn:
  767.         add     esp, 20         ; CF=0
  768.         pop     esi
  769.         ret     4
  770.  
  771. ;----------------------------------------------------------------
  772. ;
  773. ;  fs_HdRead - LFN variant for reading hard disk
  774. ;
  775. ;  Obsolete, will be replaced with filesystem-specific functions.
  776. ;
  777. ;  esi  points to filename
  778. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  779. ;       may be ebx=0 - start from first byte
  780. ;  ecx  number of bytes to read, 0+
  781. ;  edx  mem location to return data
  782. ;
  783. ;  ret ebx = bytes read or 0xffffffff file not found
  784. ;      eax = 0 ok read or other = errormsg
  785. ;
  786. ;--------------------------------------------------------------
  787. fs_HdRead:
  788.         cmp     [fs_type], 16
  789.         jz      @f
  790.         cmp     [fs_type], 32
  791.         jz      @f
  792.         cmp     [fs_type], 1
  793.         jz      ntfs_HdRead
  794.         cmp     [fs_type], 2
  795.         jz      ext2_HdRead
  796.         or      ebx, -1
  797.         mov     eax, ERROR_UNKNOWN_FS
  798.         ret
  799. @@:
  800.         sub     ebx, 4
  801.         push    ebp
  802.         mov     ebp, [fs_dependent_data_start.partition]
  803.         call    fat_Read
  804.         pop     ebp
  805.         ret
  806.  
  807. ;----------------------------------------------------------------
  808. ; fat_Read - FAT16/32 implementation of reading a file
  809. ; in:  ebp = pointer to FAT structure
  810. ; in:  esi+[esp+4] = name
  811. ; in:  ebx = pointer to parameters from sysfunc 70
  812. ; out: eax, ebx = return values for sysfunc 70
  813. ;----------------------------------------------------------------
  814. fat_Read:
  815.         call    fat_lock
  816.         push    edi
  817.         cmp     byte [esi], 0
  818.         jnz     @f
  819. .noaccess:
  820.         pop     edi
  821. .noaccess_2:
  822.         call    fat_unlock
  823.         or      ebx, -1
  824.         mov     eax, ERROR_ACCESS_DENIED
  825.         ret
  826.  
  827. @@:
  828.         stdcall hd_find_lfn, [esp+4+4]
  829.         jnc     .found
  830.         pop     edi
  831.         push    eax
  832.         call    fat_unlock
  833.         pop     eax
  834.         or      ebx, -1
  835.         ret
  836.  
  837. .found:
  838.         test    byte [edi+11], 0x10; do not allow read directories
  839.         jnz     .noaccess
  840.         cmp     dword [ebx+8], 0
  841.         jz      @f
  842.         xor     ebx, ebx
  843. .reteof:
  844.         call    fat_unlock
  845.         mov     eax, ERROR_END_OF_FILE
  846.         pop     edi
  847.         ret
  848. @@:
  849.         mov     ecx, [ebx+12]   ; size
  850.         mov     edx, [ebx+16]   ; pointer
  851.         mov     ebx, [ebx+4]    ; file offset
  852.         push    edx
  853.         push    0
  854.         mov     eax, [edi+28]
  855.         sub     eax, ebx
  856.         jb      .eof
  857.         cmp     eax, ecx
  858.         jae     @f
  859.         mov     ecx, eax
  860.         mov     byte [esp], 6
  861. @@:
  862.         mov     eax, [edi+20-2]
  863.         mov     ax, [edi+26]
  864. ; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
  865. .new_cluster:
  866.         jecxz   .new_sector
  867.         cmp     eax, 2
  868.         jb      .eof
  869.         cmp     eax, [ebp+FAT.fatRESERVED]
  870.         jae     .eof
  871.         mov     [ebp+FAT.cluster_tmp], eax
  872.         dec     eax
  873.         dec     eax
  874.         mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
  875.         imul    eax, edi
  876.         add     eax, [ebp+FAT.DATA_START]
  877. .new_sector:
  878.         test    ecx, ecx
  879.         jz      .done
  880.         sub     ebx, 512
  881.         jae     .skip
  882.         add     ebx, 512
  883.         jnz     .force_buf
  884.         cmp     ecx, 512
  885.         jb      .force_buf
  886. ; we may read directly to given buffer
  887.         push    eax ebx
  888.         mov     ebx, edx
  889.         call    fs_read32_app
  890.         test    eax, eax
  891.         pop     ebx eax
  892.         jne     .noaccess_1
  893.         add     edx, 512
  894.         sub     ecx, 512
  895.         jmp     .skip
  896. .force_buf:
  897. ; we must read sector to temporary buffer and then copy it to destination
  898.         push    eax ebx
  899.         lea     ebx, [ebp+FAT.buffer]
  900.         call    fs_read32_app
  901.         test    eax, eax
  902.         mov     eax, ebx
  903.         pop     ebx
  904.         jne     .noaccess_3
  905.         add     eax, ebx
  906.         push    ecx
  907.         add     ecx, ebx
  908.         cmp     ecx, 512
  909.         jbe     @f
  910.         mov     ecx, 512
  911. @@:
  912.         sub     ecx, ebx
  913.         mov     ebx, edx
  914.         call    memmove
  915.         add     edx, ecx
  916.         sub     [esp], ecx
  917.         pop     ecx
  918.         pop     eax
  919.         xor     ebx, ebx
  920. .skip:
  921.         inc     eax
  922.         dec     edi
  923.         jnz     .new_sector
  924.         mov     eax, [ebp+FAT.cluster_tmp]
  925.         call    get_FAT
  926.         jc      .noaccess_1
  927.  
  928.         jmp     .new_cluster
  929. .noaccess_3:
  930.         pop     eax
  931. .noaccess_1:
  932.         pop     eax
  933.         push    ERROR_DEVICE
  934. .done:
  935.         mov     ebx, edx
  936.         call    fat_unlock
  937.         pop     eax edx edi
  938.         sub     ebx, edx
  939.         ret
  940. .eof:
  941.         mov     ebx, edx
  942.         pop     eax edx
  943.         sub     ebx, edx
  944.         jmp     .reteof
  945.  
  946. ;----------------------------------------------------------------
  947. ;
  948. ;  fs_HdReadFolder - LFN variant for reading hard disk folder
  949. ;
  950. ;  Obsolete, will be replaced with filesystem-specific functions.
  951. ;
  952. ;  esi  points to filename
  953. ;  ebx  pointer to structure 32-bit number = first wanted block, 0+
  954. ;                          & flags (bitfields)
  955. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  956. ;  ecx  number of blocks to read, 0+
  957. ;  edx  mem location to return data
  958. ;
  959. ;  ret ebx = blocks read or 0xffffffff folder not found
  960. ;      eax = 0 ok read or other = errormsg
  961. ;
  962. ;--------------------------------------------------------------
  963. fs_HdReadFolder:
  964.         cmp     [fs_type], 16
  965.         jz      @f
  966.         cmp     [fs_type], 32
  967.         jz      @f
  968.         cmp     [fs_type], 1
  969.         jz      ntfs_HdReadFolder
  970.         cmp     [fs_type], 2
  971.         jz      ext2_HdReadFolder
  972.         movi    eax, ERROR_UNSUPPORTED_FS
  973.         or      ebx, -1
  974.         ret
  975. @@:
  976.         sub     ebx, 4
  977.         push    ebp
  978.         mov     ebp, [fs_dependent_data_start.partition]
  979.         call    fat_ReadFolder
  980.         pop     ebp
  981.         ret
  982.  
  983. ;----------------------------------------------------------------
  984. ; fat_ReadFolder - FAT16/32 implementation of reading a folder
  985. ; in:  ebp = pointer to FAT structure
  986. ; in:  esi+[esp+4] = name
  987. ; in:  ebx = pointer to parameters from sysfunc 70
  988. ; out: eax, ebx = return values for sysfunc 70
  989. ;----------------------------------------------------------------
  990. fat_ReadFolder:
  991.         call    fat_lock
  992.         mov     eax, [ebp+FAT.ROOT_CLUSTER]
  993.         push    edi
  994.         cmp     byte [esi], 0
  995.         jz      .doit
  996.         stdcall hd_find_lfn, [esp+4+4]
  997.         jnc     .found
  998.         pop     edi
  999.         push    eax
  1000.         call    fat_unlock
  1001.         pop     eax
  1002.         or      ebx, -1
  1003.         ret
  1004. .found:
  1005.         test    byte [edi+11], 0x10     ; do not allow read files
  1006.         jnz     .found_dir
  1007.         pop     edi
  1008.         call    fat_unlock
  1009.         or      ebx, -1
  1010.         mov     eax, ERROR_ACCESS_DENIED
  1011.         ret
  1012. .found_dir:
  1013.         mov     eax, [edi+20-2]
  1014.         mov     ax, [edi+26]    ; eax=cluster
  1015. .doit:
  1016.         push    esi
  1017.         sub     esp, 262*2      ; reserve space for LFN
  1018.         push    dword [ebx+8]   ; for fat_get_name: read ANSI/UNICODE name
  1019.         mov     edx, [ebx+16]   ; pointer to buffer
  1020. ; init header
  1021.         push    eax
  1022.         mov     edi, edx
  1023.         mov     ecx, 32/4
  1024.         xor     eax, eax
  1025.         rep stosd
  1026.         pop     eax
  1027.         mov     byte [edx], 1   ; version
  1028.         mov     esi, edi        ; esi points to BDFE
  1029.         mov     ecx, [ebx+12]   ; number of blocks to read
  1030.         mov     ebx, [ebx+4]    ; index of the first block
  1031. .new_cluster:
  1032.         mov     [ebp+FAT.cluster_tmp], eax
  1033.         test    eax, eax
  1034.         jnz     @f
  1035.         cmp     [ebp+FAT.fs_type], 32
  1036.         jz      .notfound
  1037.         mov     eax, [ebp+FAT.ROOT_START]
  1038.         push    [ebp+FAT.ROOT_SECTORS]
  1039.         push    ebx
  1040.         jmp     .new_sector
  1041. @@:
  1042.         dec     eax
  1043.         dec     eax
  1044.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1045.         push    [ebp+FAT.SECTORS_PER_CLUSTER]
  1046.         add     eax, [ebp+FAT.DATA_START]
  1047.         push    ebx
  1048. .new_sector:
  1049.         lea     ebx, [ebp+FAT.buffer]
  1050.         mov     edi, ebx
  1051.         push    eax
  1052.         call    fs_read32_sys
  1053.         test    eax, eax
  1054.         pop     eax
  1055.         jnz     .notfound2
  1056.         add     ebx, 512
  1057.         push    eax
  1058. .l1:
  1059.         push    ebp
  1060.         lea     ebp, [esp+20]
  1061.         call    fat_get_name
  1062.         pop     ebp
  1063.         jc      .l2
  1064.         cmp     byte [edi+11], 0xF
  1065.         jnz     .do_bdfe
  1066.         add     edi, 0x20
  1067.         cmp     edi, ebx
  1068.         jb      .do_bdfe
  1069.         pop     eax
  1070.         inc     eax
  1071.         dec     dword [esp+4]
  1072.         jnz     @f
  1073.         mov     eax, [ebp+FAT.cluster_tmp]
  1074.         test    eax, eax
  1075.         jz      .done
  1076.         call    get_FAT
  1077.         jc      .notfound2
  1078.         cmp     eax, 2
  1079.         jb      .done
  1080.         cmp     eax, [ebp+FAT.fatRESERVED]
  1081.         jae     .done
  1082.         push    eax
  1083.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1084.         mov     [esp+8], eax
  1085.         pop     eax
  1086.         mov     [ebp+FAT.cluster_tmp], eax
  1087.         dec     eax
  1088.         dec     eax
  1089.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1090.         add     eax, [ebp+FAT.DATA_START]
  1091. @@:
  1092.         lea     ebx, [ebp+FAT.buffer]
  1093.         mov     edi, ebx
  1094.         push    eax
  1095.         call    fs_read32_sys
  1096.         test    eax, eax
  1097.         pop     eax
  1098.         jnz     .notfound2
  1099.         add     ebx, 512
  1100.         push    eax
  1101. .do_bdfe:
  1102.         inc     dword [edx+8]   ; new file found
  1103.         dec     dword [esp+4]
  1104.         jns     .l2
  1105.         dec     ecx
  1106.         js      .l2
  1107.         inc     dword [edx+4]   ; new file block copied
  1108.         push    ebp
  1109.         lea     ebp, [esp+20]
  1110.         call    fat_entry_to_bdfe
  1111.         pop     ebp
  1112. .l2:
  1113.         add     edi, 0x20
  1114.         cmp     edi, ebx
  1115.         jb      .l1
  1116.         pop     eax
  1117.         inc     eax
  1118.         dec     dword [esp+4]
  1119.         jnz     .new_sector
  1120.         mov     eax, [ebp+FAT.cluster_tmp]
  1121.         test    eax, eax
  1122.         jz      .done
  1123.         call    get_FAT
  1124.         jc      .notfound2
  1125.         cmp     eax, 2
  1126.         jb      .done
  1127.         cmp     eax, [ebp+FAT.fatRESERVED]
  1128.         jae     .done
  1129.         push    eax
  1130.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1131.         mov     [esp+8], eax
  1132.         pop     eax
  1133.         pop     ebx
  1134.         add     esp, 4
  1135.         jmp     .new_cluster
  1136. .notfound2:
  1137.         add     esp, 8
  1138. .notfound:
  1139.         add     esp, 262*2+4
  1140.         pop     esi edi
  1141.         mov     ebx, [edx+4]
  1142.         call    fat_unlock
  1143.         mov     eax, ERROR_DEVICE
  1144.         ret
  1145. .done:
  1146.         add     esp, 262*2+4+8
  1147.         mov     ebx, [edx+4]
  1148.         xor     eax, eax
  1149.         dec     ecx
  1150.         js      @f
  1151.         mov     al, ERROR_END_OF_FILE
  1152. @@:
  1153.         push    eax
  1154.         call    fat_unlock
  1155.         pop     eax
  1156.         pop     esi edi
  1157.         ret
  1158.  
  1159. fat16_root_next:
  1160.         push    ecx
  1161.         lea     ecx, [ebp+FAT.buffer+0x200-0x20]
  1162.         cmp     edi, ecx
  1163.         jae     fat16_root_next_sector
  1164.         pop     ecx
  1165.         add     edi, 0x20
  1166.         ret     ; CF=0
  1167. fat16_root_next_sector:
  1168. ; read next sector
  1169.         push    [ebp+FAT.longname_sec2]
  1170.         pop     [ebp+FAT.longname_sec1]
  1171.         mov     ecx, [eax+4]
  1172.         push    ecx
  1173.         add     ecx, [ebp+FAT.ROOT_START]
  1174.         mov     [ebp+FAT.longname_sec2], ecx
  1175.         pop     ecx
  1176.         inc     ecx
  1177.         mov     [eax+4], ecx
  1178.         cmp     ecx, [ebp+FAT.ROOT_SECTORS]
  1179.         pop     ecx
  1180.         jb      fat16_root_first
  1181.         mov     eax, ERROR_FILE_NOT_FOUND
  1182.         stc
  1183.         ret
  1184. fat16_root_first:
  1185.         mov     eax, [eax+4]
  1186.         add     eax, [ebp+FAT.ROOT_START]
  1187.         push    ebx
  1188.         lea     edi, [ebp+FAT.buffer]
  1189.         mov     ebx, edi
  1190.         call    fs_read32_sys
  1191.         pop     ebx
  1192.         test    eax, eax
  1193.         jnz     .readerr
  1194.         ret     ; CF=0
  1195. .readerr:
  1196.         mov     eax, ERROR_DEVICE
  1197.         stc
  1198.         ret
  1199. .notfound:
  1200.         mov     eax, ERROR_FILE_NOT_FOUND
  1201.         stc
  1202.         ret
  1203. fat16_root_begin_write:
  1204.         push    edi eax
  1205.         call    fat16_root_first
  1206.         pop     eax edi
  1207.         ret
  1208. fat16_root_end_write:
  1209.         pusha
  1210.         mov     eax, [eax+4]
  1211.         add     eax, [ebp+FAT.ROOT_START]
  1212.         lea     ebx, [ebp+FAT.buffer]
  1213.         call    fs_write32_sys
  1214.         popa
  1215.         ret
  1216. fat16_root_next_write:
  1217.         push    ecx
  1218.         lea     ecx, [ebp+FAT.buffer+0x200]
  1219.         cmp     edi, ecx
  1220.         jae     @f
  1221.         pop     ecx
  1222.         ret
  1223. @@:
  1224.         call    fat16_root_end_write
  1225.         jmp     fat16_root_next_sector
  1226. fat16_root_extend_dir:
  1227.         stc
  1228.         ret
  1229.  
  1230. fat_notroot_next:
  1231.         push    ecx
  1232.         lea     ecx, [ebp+FAT.buffer+0x200-0x20]
  1233.         cmp     edi, ecx
  1234.         jae     fat_notroot_next_sector
  1235.         pop     ecx
  1236.         add     edi, 0x20
  1237.         ret     ; CF=0
  1238. fat_notroot_next_sector:
  1239.         push    [ebp+FAT.longname_sec2]
  1240.         pop     [ebp+FAT.longname_sec1]
  1241.         push    eax
  1242.         call    fat_get_sector
  1243.         mov     [ebp+FAT.longname_sec2], eax
  1244.         pop     eax
  1245.         mov     ecx, [eax+4]
  1246.         inc     ecx
  1247.         cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1248.         jae     fat_notroot_next_cluster
  1249.         mov     [eax+4], ecx
  1250.         jmp     @f
  1251. fat_notroot_next_cluster:
  1252.         push    eax
  1253.         mov     eax, [eax]
  1254.         call    get_FAT
  1255.         mov     ecx, eax
  1256.         pop     eax
  1257.         jc      fat_notroot_first.deverr
  1258.         cmp     ecx, 2
  1259.         jb      fat_notroot_next_err
  1260.         cmp     ecx, [ebp+FAT.fatRESERVED]
  1261.         jae     fat_notroot_next_err
  1262.         mov     [eax], ecx
  1263.         and     dword [eax+4], 0
  1264. @@:
  1265.         pop     ecx
  1266. fat_notroot_first:
  1267.         call    fat_get_sector
  1268.         push    ebx
  1269.         lea     edi, [ebp+FAT.buffer]
  1270.         mov     ebx, edi
  1271.         call    fs_read32_sys
  1272.         pop     ebx
  1273.         test    eax, eax
  1274.         jz      .ret ; CF=0
  1275.         push    ecx
  1276. .deverr:
  1277.         pop     ecx
  1278.         mov     eax, ERROR_DEVICE
  1279.         stc
  1280. .ret:
  1281.         ret
  1282. fat_notroot_next_err:
  1283.         pop     ecx
  1284.         mov     eax, ERROR_FILE_NOT_FOUND
  1285.         stc
  1286.         ret
  1287. fat_notroot_begin_write:
  1288.         push    eax edi
  1289.         call    fat_notroot_first
  1290.         pop     edi eax
  1291.         ret
  1292. fat_notroot_end_write:
  1293.         call    fat_get_sector
  1294.         push    ebx
  1295.         lea     ebx, [ebp+FAT.buffer]
  1296.         call    fs_write32_sys
  1297.         pop     ebx
  1298.         ret
  1299. fat_notroot_next_write:
  1300.         push    ecx
  1301.         lea     ecx, [ebp+FAT.buffer+0x200]
  1302.         cmp     edi, ecx
  1303.         jae     @f
  1304.         pop     ecx
  1305.         ret
  1306. @@:
  1307.         push    eax
  1308.         call    fat_notroot_end_write
  1309.         pop     eax
  1310.         jmp     fat_notroot_next_sector
  1311. fat_notroot_extend_dir:
  1312.         push    eax
  1313.         call    get_free_FAT
  1314.         jnc     .found
  1315.         pop     eax
  1316.         ret     ; CF=1
  1317. .found:
  1318.         push    edx
  1319.         mov     edx, [ebp+FAT.fatEND]
  1320.         call    set_FAT
  1321.         jc      .writeerr
  1322.         mov     edx, eax
  1323.         mov     eax, [esp+4]
  1324.         mov     eax, [eax]
  1325.         push    edx
  1326.         call    set_FAT
  1327.         pop     edx
  1328.         jnc     @f
  1329. .writeerr:
  1330.         pop     edx
  1331.         pop     eax
  1332.         stc
  1333.         ret
  1334. @@:
  1335.         push    ecx
  1336.         or      ecx, -1
  1337.         call    add_disk_free_space
  1338. ; zero new cluster
  1339.         mov     ecx, 512/4
  1340.         lea     edi, [ebp+FAT.buffer]
  1341.         push    edi
  1342.         xor     eax, eax
  1343.         rep stosd
  1344.         pop     edi
  1345.         pop     ecx
  1346.         mov     eax, [esp+4]
  1347.         mov     [eax], edx
  1348.         and     dword [eax+4], 0
  1349.         pop     edx
  1350.         mov     eax, [eax]
  1351.         dec     eax
  1352.         dec     eax
  1353.         push    ebx ecx
  1354.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1355.         imul    eax, ecx
  1356.         add     eax, [ebp+FAT.DATA_START]
  1357.         mov     ebx, edi
  1358. @@:
  1359.         push    eax
  1360.         call    fs_write32_sys
  1361.         pop     eax
  1362.         inc     eax
  1363.         loop    @b
  1364.         pop     ecx ebx eax
  1365.         clc
  1366.         ret
  1367.  
  1368. fat_get_sector:
  1369.         push    ecx
  1370.         mov     ecx, [eax]
  1371.         dec     ecx
  1372.         dec     ecx
  1373.         imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1374.         add     ecx, [ebp+FAT.DATA_START]
  1375.         add     ecx, [eax+4]
  1376.         mov     eax, ecx
  1377.         pop     ecx
  1378.         ret
  1379.  
  1380. ;----------------------------------------------------------------
  1381. ;
  1382. ;  fs_HdRewrite - LFN variant for writing hard disk
  1383. ;
  1384. ;  Obsolete, will be replaced with filesystem-specific functions.
  1385. ;
  1386. ;  esi  points to filename
  1387. ;  ebx  ignored (reserved)
  1388. ;  ecx  number of bytes to write, 0+
  1389. ;  edx  mem location to data
  1390. ;
  1391. ;  ret ebx = number of written bytes
  1392. ;      eax = 0 ok read or other = errormsg
  1393. ;
  1394. ;--------------------------------------------------------------
  1395. fs_HdCreateFolder:
  1396.         mov     al, 1
  1397.         jmp     fs_HdRewrite.common
  1398.  
  1399. fs_HdRewrite:
  1400.         xor     eax, eax
  1401. .common:
  1402.         cmp     [fs_type], 16
  1403.         jz      @f
  1404.         cmp     [fs_type], 32
  1405.         jz      @f
  1406.         cmp     [fs_type], 1
  1407.         jz      ntfs_HdRewrite
  1408.         cmp     [fs_type], 2
  1409.         jz      ext2_HdRewrite
  1410.         mov     eax, ERROR_UNKNOWN_FS
  1411.         xor     ebx, ebx
  1412.         ret
  1413. @@:
  1414.         sub     ebx, 4
  1415.         push    ebp
  1416.         mov     ebp, [fs_dependent_data_start.partition]
  1417.         test    eax, eax
  1418.         mov     eax, fat_CreateFolder
  1419.         jnz     @f
  1420.         mov     eax, fat_Rewrite
  1421. @@:
  1422.         call    eax
  1423.         pop     ebp
  1424.         ret
  1425.  
  1426. fshrad:
  1427.         call    fat_unlock
  1428.         mov     eax, ERROR_ACCESS_DENIED
  1429.         xor     ebx, ebx
  1430.         ret
  1431.  
  1432. ;----------------------------------------------------------------
  1433. ; fat_CreateFolder - FAT16/32 implementation of creating a folder
  1434. ; in:  ebp = pointer to FAT structure
  1435. ; in:  esi+[esp+4] = name
  1436. ; in:  ebx = pointer to parameters from sysfunc 70
  1437. ; out: eax, ebx = return values for sysfunc 70
  1438. ;----------------------------------------------------------------
  1439. fat_CreateFolder:
  1440.         push    1
  1441.         jmp     fat_Rewrite.common
  1442.  
  1443. ;----------------------------------------------------------------
  1444. ; fat_HdRewrite - FAT16/32 implementation of creating a new file
  1445. ; in:  ebp = pointer to FAT structure
  1446. ; in:  esi+[esp+4] = name
  1447. ; in:  ebx = pointer to parameters from sysfunc 70
  1448. ; out: eax, ebx = return values for sysfunc 70
  1449. ;----------------------------------------------------------------
  1450. fat_Rewrite:
  1451.         push    0
  1452. .common:
  1453.         call    fat_lock
  1454.         pop     eax
  1455.         cmp     byte [esi], 0
  1456.         jz      fshrad
  1457.         mov     ecx, [ebx+12]
  1458.         mov     edx, [ebx+16]
  1459.         pushad
  1460.         xor     edi, edi
  1461.         mov     edx, [esp+4+20h]
  1462.         push    esi
  1463.         test    edx, edx
  1464.         jz      @f
  1465.         mov     esi, edx
  1466. @@:
  1467.         lodsb
  1468.         test    al, al
  1469.         jz      @f
  1470.         cmp     al, '/'
  1471.         jnz     @b
  1472.         lea     edi, [esi-1]
  1473.         jmp     @b
  1474. @@:
  1475.         pop     esi
  1476.         test    edi, edi
  1477.         jnz     .noroot
  1478.         test    edx, edx
  1479.         jnz     .hasebp
  1480.         mov     edx, [ebp+FAT.ROOT_CLUSTER]
  1481.         cmp     [ebp+FAT.fs_type], 32
  1482.         jz      .pushnotroot
  1483.         xor     edx, edx
  1484.         push    edx
  1485.         push    fat16_root_extend_dir
  1486.         push    fat16_root_end_write
  1487.         push    fat16_root_next_write
  1488.         push    fat16_root_begin_write
  1489.         push    edx
  1490.         push    edx
  1491.         push    fat16_root_first
  1492.         push    fat16_root_next
  1493.         jmp     .common1
  1494. .hasebp:
  1495.         mov     eax, ERROR_ACCESS_DENIED
  1496.         cmp     byte [edx], 0
  1497.         jz      .ret1
  1498.         stdcall hd_find_lfn, 0
  1499.         mov     esi, [esp+4+20h]
  1500.         jc      .ret1
  1501.         jmp     .common0
  1502. .noroot:
  1503.         mov     eax, ERROR_ACCESS_DENIED
  1504.         cmp     byte [edi+1], 0
  1505.         jz      .ret1
  1506. ; check existence
  1507.         mov     byte [edi], 0
  1508.         push    edi
  1509.         stdcall hd_find_lfn, [esp+4+24h]
  1510.         pop     esi
  1511.         mov     byte [esi], '/'
  1512.         jnc     @f
  1513. .notfound0:
  1514.         mov     eax, ERROR_FILE_NOT_FOUND
  1515. .ret1:
  1516.         mov     [esp+28], eax
  1517.         call    fat_unlock
  1518.         popad
  1519.         xor     ebx, ebx
  1520.         ret
  1521. @@:
  1522.         inc     esi
  1523. .common0:
  1524.         test    byte [edi+11], 0x10     ; must be directory
  1525.         mov     eax, ERROR_ACCESS_DENIED
  1526.         jz      .ret1
  1527.         mov     edx, [edi+20-2]
  1528.         mov     dx, [edi+26]            ; ebp=cluster
  1529.         mov     eax, ERROR_FAT_TABLE
  1530.         cmp     edx, 2
  1531.         jb      .ret1
  1532. .pushnotroot:
  1533.         push    edx
  1534.         push    fat_notroot_extend_dir
  1535.         push    fat_notroot_end_write
  1536.         push    fat_notroot_next_write
  1537.         push    fat_notroot_begin_write
  1538.         push    0
  1539.         push    edx
  1540.         push    fat_notroot_first
  1541.         push    fat_notroot_next
  1542. .common1:
  1543.         call    fat_find_lfn
  1544.         jc      .notfound
  1545. ; found
  1546.         test    byte [edi+11], 10h
  1547.         jz      .exists_file
  1548. ; found directory; if we are creating directory, return OK,
  1549. ;                  if we are creating file, say "access denied"
  1550.         add     esp, 36
  1551.         call    fat_unlock
  1552.         popad
  1553.         test    al, al
  1554.         mov     eax, ERROR_ACCESS_DENIED
  1555.         jz      @f
  1556.         mov     al, 0
  1557. @@:
  1558.         xor     ebx, ebx
  1559.         ret
  1560. .exists_file:
  1561. ; found file; if we are creating directory, return "access denied",
  1562. ;             if we are creating file, delete existing file and continue
  1563.         cmp     byte [esp+36+28], 0
  1564.         jz      @f
  1565.         add     esp, 36
  1566.         call    fat_unlock
  1567.         popad
  1568.         mov     eax, ERROR_ACCESS_DENIED
  1569.         xor     ebx, ebx
  1570.         ret
  1571. @@:
  1572. ; delete FAT chain
  1573.         push    edi
  1574.         xor     eax, eax
  1575.         mov     dword [edi+28], eax     ; zero size
  1576.         xor     ecx, ecx
  1577.         mov     eax, [edi+20-2]
  1578.         mov     ax, [edi+26]
  1579.         mov     word [edi+20], cx
  1580.         mov     word [edi+26], cx
  1581.         test    eax, eax
  1582.         jz      .done1
  1583. @@:
  1584.         cmp     eax, [ebp+FAT.fatRESERVED]
  1585.         jae     .done1
  1586.         push    edx
  1587.         xor     edx, edx
  1588.         call    set_FAT
  1589.         mov     eax, edx
  1590.         pop     edx
  1591.         jc      .done1
  1592.         inc     ecx
  1593.         jmp     @b
  1594. .done1:
  1595.         pop     edi
  1596.         call    get_time_for_file
  1597.         mov     [edi+22], ax
  1598.         call    get_date_for_file
  1599.         mov     [edi+24], ax
  1600.         mov     [edi+18], ax
  1601.         or      byte [edi+11], 20h      ; set 'archive' attribute
  1602.         jmp     .doit
  1603. .notfound:
  1604. ; file is not found; generate short name
  1605.         call    fat_name_is_legal
  1606.         jc      @f
  1607.         add     esp, 36
  1608.         call    fat_unlock
  1609.         popad
  1610.         mov     eax, ERROR_FILE_NOT_FOUND
  1611.         xor     ebx, ebx
  1612.         ret
  1613. @@:
  1614.         sub     esp, 12
  1615.         mov     edi, esp
  1616.         call    fat_gen_short_name
  1617. .test_short_name_loop:
  1618.         push    esi edi ecx
  1619.         mov     esi, edi
  1620.         lea     eax, [esp+12+12+8]
  1621.         mov     edx, [eax+24]
  1622.         mov     [eax], edx
  1623.         and     dword [eax+4], 0
  1624.         call    dword [eax-4]
  1625.         jc      .found
  1626. .test_short_name_entry:
  1627.         cmp     byte [edi+11], 0xF
  1628.         jz      .test_short_name_cont
  1629.         mov     ecx, 11
  1630.         push    esi edi
  1631.         repz cmpsb
  1632.         pop     edi esi
  1633.         jz      .short_name_found
  1634. .test_short_name_cont:
  1635.         lea     eax, [esp+12+12+8]
  1636.         call    dword [eax-8]
  1637.         jnc     .test_short_name_entry
  1638.         jmp     .found
  1639. .short_name_found:
  1640.         pop     ecx edi esi
  1641.         call    fat_next_short_name
  1642.         jnc     .test_short_name_loop
  1643. .disk_full:
  1644.         add     esp, 12+36
  1645.         call    fat_unlock
  1646.         popa
  1647.         mov     eax, ERROR_DISK_FULL
  1648.         xor     ebx, ebx
  1649.         ret
  1650. .found:
  1651.         pop     ecx edi esi
  1652. ; now find space in directory
  1653. ; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
  1654.         mov     al, '~'
  1655.         push    ecx edi
  1656.         mov     ecx, 8
  1657.         repnz scasb
  1658.         movi    eax, 1     ; 1 entry
  1659.         jnz     .notilde
  1660. ; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
  1661.         xor     eax, eax
  1662. @@:
  1663.         cmp     byte [esi], 0
  1664.         jz      @f
  1665.         inc     esi
  1666.         inc     eax
  1667.         jmp     @b
  1668. @@:
  1669.         sub     esi, eax
  1670.         add     eax, 12+13
  1671.         mov     ecx, 13
  1672.         push    edx
  1673.         cdq
  1674.         div     ecx
  1675.         pop     edx
  1676. .notilde:
  1677.         push    -1
  1678.         push    -1
  1679.         push    -1
  1680. ; find <eax> successive entries in directory
  1681.         xor     ecx, ecx
  1682.         push    eax
  1683.         lea     eax, [esp+16+8+12+8]
  1684.         mov     edx, [eax+24]
  1685.         mov     [eax], edx
  1686.         and     dword [eax+4], 0
  1687.         call    dword [eax-4]
  1688.         pop     eax
  1689.         jnc     .scan_dir
  1690. .fsfrfe3:
  1691.         add     esp, 12+8+12+36
  1692.         call    fat_unlock
  1693.         popad
  1694.         mov     eax, ERROR_DEVICE
  1695.         xor     ebx, ebx
  1696.         ret
  1697. .scan_dir:
  1698.         cmp     byte [edi], 0
  1699.         jz      .free
  1700.         cmp     byte [edi], 0xE5
  1701.         jz      .free
  1702.         xor     ecx, ecx
  1703. .scan_cont:
  1704.         push    eax
  1705.         lea     eax, [esp+16+8+12+8]
  1706.         call    dword [eax-8]
  1707.         mov     edx, eax
  1708.         pop     eax
  1709.         jnc     .scan_dir
  1710.         cmp     edx, ERROR_DEVICE
  1711.         jz      .fsfrfe3
  1712.         push    eax
  1713.         lea     eax, [esp+16+8+12+8]
  1714.         call    dword [eax+20]          ; extend directory
  1715.         pop     eax
  1716.         jnc     .scan_dir
  1717.         add     esp, 12+8+12+36
  1718.         call    fat_unlock
  1719.         popad
  1720.         mov     eax, ERROR_DISK_FULL
  1721.         xor     ebx, ebx
  1722.         ret
  1723. .free:
  1724.         test    ecx, ecx
  1725.         jnz     @f
  1726.         mov     [esp], edi
  1727.         mov     ecx, [esp+12+8+12+8]
  1728.         mov     [esp+4], ecx
  1729.         mov     ecx, [esp+12+8+12+12]
  1730.         mov     [esp+8], ecx
  1731.         xor     ecx, ecx
  1732. @@:
  1733.         inc     ecx
  1734.         cmp     ecx, eax
  1735.         jb      .scan_cont
  1736. ; found!
  1737.         push    esi ecx
  1738. ; If creating a directory, allocate one data cluster now and fail immediately
  1739. ; if this is impossible. This prevents from creating an invalid directory entry
  1740. ; on a full disk.
  1741. ; yup, the argument is quite non-intuitive... but what should I do if
  1742. ; the entire function uses such arguments? BTW, it refers to al from pushad,
  1743. ; which in turn is filled with 0 in fat_Rewrite and 1 in fat_CreateFolder.
  1744.         cmp     byte [esp+8+12+8+12+36+28], 0
  1745.         jz      .no.preallocate.folder.data
  1746.         call    get_free_FAT
  1747.         jnc     @f
  1748.         add     esp, 8+12+8
  1749.         jmp     .disk_full
  1750. @@:
  1751.         mov     [esp+8+12+8+12+36+20], eax ; store the cluster somewhere
  1752. .no.preallocate.folder.data:
  1753. ; calculate name checksum
  1754.         mov     esi, [esp+8+12]
  1755.         mov     ecx, 11
  1756.         xor     eax, eax
  1757. @@:
  1758.         ror     al, 1
  1759.         add     al, [esi]
  1760.         inc     esi
  1761.         loop    @b
  1762.         pop     ecx esi
  1763.         pop     edi
  1764.         pop     dword [esp+8+12+12]
  1765.         pop     dword [esp+8+12+12]
  1766. ; edi points to first entry in free chunk
  1767.         dec     ecx
  1768.         jz      .nolfn
  1769.         push    esi
  1770.         push    eax
  1771.         lea     eax, [esp+8+8+12+8]
  1772.         call    dword [eax+8]         ; begin write
  1773.         mov     al, 40h
  1774. .writelfn:
  1775.         or      al, cl
  1776.         mov     esi, [esp+4]
  1777.         push    ecx
  1778.         dec     ecx
  1779.         imul    ecx, 13
  1780.         add     esi, ecx
  1781.         stosb
  1782.         mov     cl, 5
  1783.         call    fs_RamdiskRewrite.read_symbols
  1784.         mov     ax, 0xF
  1785.         stosw
  1786.         mov     al, [esp+4]
  1787.         stosb
  1788.         mov     cl, 6
  1789.         call    fs_RamdiskRewrite.read_symbols
  1790.         xor     eax, eax
  1791.         stosw
  1792.         mov     cl, 2
  1793.         call    fs_RamdiskRewrite.read_symbols
  1794.         pop     ecx
  1795.         lea     eax, [esp+8+8+12+8]
  1796.         call    dword [eax+12]         ; next write
  1797.         xor     eax, eax
  1798.         loop    .writelfn
  1799.         pop     eax
  1800.         pop     esi
  1801. ;        lea     eax, [esp+8+12+8]
  1802. ;        call    dword [eax+16]          ; end write
  1803. .nolfn:
  1804.         xchg    esi, [esp]
  1805.         mov     ecx, 11
  1806.         rep movsb
  1807.         mov     word [edi], 20h         ; attributes
  1808.         sub     edi, 11
  1809.         pop     esi ecx
  1810.         add     esp, 12
  1811.         mov     byte [edi+13], 0        ; tenths of a second at file creation time
  1812.         call    get_time_for_file
  1813.         mov     [edi+14], ax            ; creation time
  1814.         mov     [edi+22], ax            ; last write time
  1815.         call    get_date_for_file
  1816.         mov     [edi+16], ax            ; creation date
  1817.         mov     [edi+24], ax            ; last write date
  1818.         mov     [edi+18], ax            ; last access date
  1819.         xor     ecx, ecx
  1820.         mov     word [edi+20], cx       ; high word of cluster
  1821.         mov     word [edi+26], cx       ; low word of cluster - to be filled
  1822.         mov     dword [edi+28], ecx     ; file size - to be filled
  1823.         cmp     byte [esp+36+28], cl
  1824.         jz      .doit
  1825. ; create directory
  1826.         mov     byte [edi+11], 10h      ; attributes: folder
  1827.         mov     esi, edi
  1828.         lea     eax, [esp+8]
  1829.         call    dword [eax+16]  ; flush directory
  1830.         mov     eax, [esp+36+20] ; extract saved cluster
  1831.         mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
  1832.         push    ecx
  1833.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1834.         shl     ecx, 9
  1835.         push    ecx
  1836.         push    edi
  1837.         jmp     .doit2
  1838. .doit:
  1839.         mov     esi, [esp+36+20]
  1840.         lea     eax, [esp+8]
  1841.         call    dword [eax+16]  ; flush directory
  1842.         push    ecx
  1843.         mov     ecx, [esp+4+36+24]
  1844.         push    ecx
  1845.         push    edi
  1846.         test    ecx, ecx
  1847.         jz      .done
  1848.         call    get_free_FAT
  1849.         jc      .diskfull
  1850. .doit2:
  1851.         push    eax
  1852.         mov     [edi+26], ax
  1853.         shr     eax, 16
  1854.         mov     [edi+20], ax
  1855.         lea     eax, [esp+16+8]
  1856.         call    dword [eax+16]  ; flush directory
  1857.         pop     eax
  1858.         push    edx
  1859.         mov     edx, [ebp+FAT.fatEND]
  1860.         call    set_FAT
  1861.         pop     edx
  1862. .write_cluster:
  1863.         push    eax
  1864.         dec     eax
  1865.         dec     eax
  1866.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  1867.         add     eax, [ebp+FAT.DATA_START]
  1868.         push    [ebp+FAT.SECTORS_PER_CLUSTER]
  1869. ; write data
  1870. .write_sector:
  1871.         cmp     byte [esp+20+36+28], 0
  1872.         jnz     .writedir
  1873.         mov     ecx, 512
  1874.         cmp     dword [esp+12], ecx
  1875.         jb      .writeshort
  1876. ; we can write directly from given buffer
  1877.         mov     ebx, esi
  1878.         add     esi, ecx
  1879.         jmp     .writecommon
  1880. .writeshort:
  1881.         mov     ecx, [esp+12]
  1882.         push    ecx
  1883.         lea     edi, [ebp+FAT.buffer]
  1884.         mov     ebx, edi
  1885.         rep movsb
  1886. .writedircont:
  1887.         lea     ecx, [ebp+FAT.buffer+0x200]
  1888.         sub     ecx, edi
  1889.         push    eax
  1890.         xor     eax, eax
  1891.         rep stosb
  1892.         pop     eax
  1893.         pop     ecx
  1894. .writecommon:
  1895.         push    eax
  1896.         call    fs_write32_app
  1897.         test    eax, eax
  1898.         pop     eax
  1899.         jnz     .writeerr
  1900.         inc     eax
  1901.         sub     dword [esp+12], ecx
  1902.         jz      .writedone
  1903.         dec     dword [esp]
  1904.         jnz     .write_sector
  1905.         pop     eax
  1906. ; allocate new cluster
  1907.         pop     eax
  1908.         mov     ecx, eax
  1909.         call    get_free_FAT
  1910.         jc      .diskfull
  1911.         push    edx
  1912.         mov     edx, [ebp+FAT.fatEND]
  1913.         call    set_FAT
  1914.         xchg    eax, ecx
  1915.         mov     edx, ecx
  1916.         call    set_FAT
  1917.         pop     edx
  1918.         xchg    eax, ecx
  1919.         jmp     .write_cluster
  1920. .diskfull:
  1921.         mov     eax, ERROR_DISK_FULL
  1922.         jmp     .ret
  1923. .writeerr:
  1924.         pop     eax eax
  1925.         sub     esi, ecx
  1926.         mov     eax, ERROR_DEVICE
  1927.         jmp     .ret
  1928. .writedone:
  1929.         pop     eax eax
  1930. .done:
  1931.         xor     eax, eax
  1932. .ret:
  1933.         pop     edi ecx
  1934.         sub     esi, [esp+4+36+20]
  1935.         mov     [esp+4+36+28], eax
  1936.         mov     [esp+4+36+16], esi
  1937.         lea     eax, [esp+12]
  1938.         call    dword [eax+8]
  1939.         mov     [edi+28], esi
  1940.         call    dword [eax+16]
  1941.         mov     [esp+36+16], ebx
  1942.         lea     eax, [esi+511]
  1943.         shr     eax, 9
  1944.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1945.         lea     eax, [eax+ecx-1]
  1946.         xor     edx, edx
  1947.         div     ecx
  1948.         pop     ecx
  1949.         sub     ecx, eax
  1950.         call    add_disk_free_space
  1951.         add     esp, 36
  1952.         call    update_disk
  1953.         call    fat_unlock
  1954.         popad
  1955.         ret
  1956. .writedir:
  1957.         push    512
  1958.         lea     edi, [ebp+FAT.buffer]
  1959.         mov     ebx, edi
  1960.         mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  1961.         shl     ecx, 9
  1962.         cmp     ecx, [esp+16]
  1963.         jnz     .writedircont
  1964.         dec     dword [esp+20]
  1965.         push    esi
  1966.         mov     ecx, 32/4
  1967.         rep movsd
  1968.         pop     esi
  1969.         mov     dword [edi-32], '.   '
  1970.         mov     dword [edi-32+4], '    '
  1971.         mov     dword [edi-32+8], '    '
  1972.         mov     byte [edi-32+11], 10h
  1973.         push    esi
  1974.         mov     ecx, 32/4
  1975.         rep movsd
  1976.         pop     esi
  1977.         mov     dword [edi-32], '..  '
  1978.         mov     dword [edi-32+4], '    '
  1979.         mov     dword [edi-32+8], '    '
  1980.         mov     byte [edi-32+11], 10h
  1981.         mov     ecx, [esp+20+36]
  1982.         cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
  1983.         jnz     @f
  1984.         xor     ecx, ecx
  1985. @@:
  1986.         mov     word [edi-32+26], cx
  1987.         shr     ecx, 16
  1988.         mov     [edi-32+20], cx
  1989.         jmp     .writedircont
  1990.  
  1991. ;----------------------------------------------------------------
  1992. ;
  1993. ;  fs_HdWrite - LFN variant for writing to hard disk
  1994. ;
  1995. ;  Obsolete, will be replaced with filesystem-specific functions.
  1996. ;
  1997. ;  esi  points to filename
  1998. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1999. ;       may be ebx=0 - start from first byte
  2000. ;  ecx  number of bytes to write, 0+
  2001. ;  edx  mem location to data
  2002. ;
  2003. ;  ret ebx = bytes written (maybe 0)
  2004. ;      eax = 0 ok write or other = errormsg
  2005. ;
  2006. ;--------------------------------------------------------------
  2007. fat_Write.access_denied:
  2008.         push    ERROR_ACCESS_DENIED
  2009. fs_HdWrite.ret0:
  2010.         pop     eax
  2011.         xor     ebx, ebx
  2012.         ret
  2013.  
  2014. fs_HdWrite.ret11:
  2015.         push    ERROR_DEVICE
  2016.         jmp     fs_HdWrite.ret0
  2017.  
  2018. fs_HdWrite:
  2019.         cmp     [fs_type], 16
  2020.         jz      @f
  2021.         cmp     [fs_type], 32
  2022.         jz      @f
  2023.         cmp     [fs_type], 1
  2024.         jz      ntfs_HdWrite
  2025.         cmp     [fs_type], 2
  2026.         jz      ext2_HdWrite
  2027.         push    ERROR_UNKNOWN_FS
  2028.         jmp     .ret0
  2029. @@:
  2030.         sub     ebx, 4
  2031.         push    ebp
  2032.         mov     ebp, [fs_dependent_data_start.partition]
  2033.         call    fat_Write
  2034.         pop     ebp
  2035.         ret
  2036.  
  2037. ;----------------------------------------------------------------
  2038. ; fat_Write - FAT16/32 implementation of writing to file
  2039. ; in:  ebp = pointer to FAT structure
  2040. ; in:  esi+[esp+4] = name
  2041. ; in:  ebx = pointer to parameters from sysfunc 70
  2042. ; out: eax, ebx = return values for sysfunc 70
  2043. ;----------------------------------------------------------------
  2044. fat_Write:
  2045.         cmp     byte [esi], 0
  2046.         jz      .access_denied
  2047.         call    fat_lock
  2048.         push    edi
  2049.         stdcall hd_find_lfn, [esp+4+4]
  2050.         jnc     .found
  2051.         pop     edi
  2052.         push    eax
  2053.         call    fat_unlock
  2054.         jmp     fs_HdWrite.ret0
  2055. .found:
  2056. ; FAT does not support files larger than 4GB
  2057.         cmp     dword [ebx+8], 0
  2058.         jz      @f
  2059. .eof:
  2060.         pop     edi
  2061.         push    ERROR_END_OF_FILE
  2062.         call    fat_unlock
  2063.         jmp     fs_HdWrite.ret0
  2064. @@:
  2065.         mov     ecx, [ebx+12]
  2066.         mov     edx, [ebx+16]
  2067.         mov     ebx, [ebx+4]
  2068. ; now edi points to direntry, ebx=start byte to write,
  2069. ; ecx=number of bytes to write, edx=data pointer
  2070.  
  2071. ; extend file if needed
  2072.         add     ecx, ebx
  2073.         jc      .eof    ; FAT does not support files larger than 4GB
  2074.         push    edx
  2075.         push    eax     ; save directory sector
  2076.         push    0       ; return value=0
  2077.  
  2078.         call    get_time_for_file
  2079.         mov     [edi+22], ax            ; last write time
  2080.         call    get_date_for_file
  2081.         mov     [edi+24], ax            ; last write date
  2082.         mov     [edi+18], ax            ; last access date
  2083.  
  2084.         push    dword [edi+28]          ; save current file size
  2085.         cmp     ecx, [edi+28]
  2086.         jbe     .length_ok
  2087.         cmp     ecx, ebx
  2088.         jz      .length_ok
  2089.         call    hd_extend_file
  2090.         jnc     .length_ok
  2091.         mov     [esp+4], eax
  2092. ; hd_extend_file can return three error codes: FAT table error, device error or disk full.
  2093. ; First two cases are fatal errors, in third case we may write some data
  2094.         cmp     al, ERROR_DISK_FULL
  2095.         jz      .disk_full
  2096.         call    fat_unlock
  2097.         pop     eax
  2098.         pop     eax
  2099.         pop     ecx
  2100.         pop     edx
  2101.         pop     edi
  2102.         xor     ebx, ebx
  2103.         ret
  2104. .disk_full:
  2105. ; correct number of bytes to write
  2106.         mov     ecx, [edi+28]
  2107.         cmp     ecx, ebx
  2108.         ja      .length_ok
  2109.         push    0
  2110. .ret:
  2111.         pop     eax
  2112.         sub     edx, [esp+12]
  2113.         mov     ebx, edx        ; ebx=number of written bytes
  2114.         call    update_disk
  2115.         test    eax, eax
  2116.         jz      @f
  2117.         mov     byte [esp+4], ERROR_DEVICE
  2118. @@:
  2119.         call    fat_unlock
  2120.         pop     eax
  2121.         pop     eax
  2122.         pop     ecx
  2123.         pop     edx
  2124.         pop     edi
  2125.         ret
  2126. .length_ok:
  2127.         mov     esi, [edi+28]
  2128.         mov     eax, [edi+20-2]
  2129.         mov     ax, [edi+26]
  2130.         mov     edi, eax        ; edi=current cluster
  2131.         push    0               ; current sector in cluster
  2132. ; save directory
  2133.         mov     eax, [esp+12]
  2134.         push    ebx
  2135.         lea     ebx, [ebp+FAT.buffer]
  2136.         call    fs_write32_sys
  2137.         pop     ebx
  2138.         test    eax, eax
  2139.         jz      @f
  2140. .device_err:
  2141.         mov     byte [esp+8], ERROR_DEVICE
  2142.         jmp     .ret
  2143. .fat_err:
  2144.         mov     byte [esp+8], ERROR_FAT_TABLE
  2145.         jmp     .ret
  2146. @@:
  2147.  
  2148. ; now ebx=start pos, ecx=end pos, both lie inside file
  2149.         sub     ecx, ebx
  2150.         jz      .ret
  2151. .write_loop:
  2152. ; skip unmodified sectors
  2153.         cmp     dword [esp+4], 0x200
  2154.         jb      .modify
  2155.         sub     ebx, 0x200
  2156.         jae     .skip
  2157.         add     ebx, 0x200
  2158. .modify:
  2159. ; get length of data in current sector
  2160.         push    ecx
  2161.         sub     ebx, 0x200
  2162.         jb      .hasdata
  2163.         neg     ebx
  2164.         xor     ecx, ecx
  2165.         jmp     @f
  2166. .hasdata:
  2167.         neg     ebx
  2168.         cmp     ecx, ebx
  2169.         jbe     @f
  2170.         mov     ecx, ebx
  2171. @@:
  2172. ; get current sector number
  2173.         mov     eax, edi
  2174.         dec     eax
  2175.         dec     eax
  2176.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2177.         add     eax, [ebp+FAT.DATA_START]
  2178.         add     eax, [esp+4]
  2179. ; load sector if needed
  2180.         cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
  2181.         jz      .noread
  2182.         cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
  2183.         jz      .noread
  2184.         cmp     ecx, esi        ; (same for the last sector)
  2185.         jz      .noread
  2186.         push    eax ebx
  2187.         lea     ebx, [ebp+FAT.buffer]
  2188.         call    fs_read32_app
  2189.         test    eax, eax
  2190.         pop     ebx eax
  2191.         jz      @f
  2192. .device_err2:
  2193.         pop     ecx
  2194.         jmp     .device_err
  2195. @@:
  2196. .noread:
  2197. ; zero uninitialized data if file was extended (because hd_extend_file does not this)
  2198.         push    eax ecx edi
  2199.         xor     eax, eax
  2200.         mov     ecx, 0x200
  2201.         sub     ecx, [esp+8+12]
  2202.         jbe     @f
  2203.         lea     edi, [ebp+FAT.buffer]
  2204.         add     edi, [esp+8+12]
  2205.         rep stosb
  2206. @@:
  2207. ; zero uninitialized data in the last sector
  2208.         mov     ecx, 0x200
  2209.         sub     ecx, esi
  2210.         jbe     @f
  2211.         lea     edi, [ebp+FAT.buffer+esi]
  2212.         rep stosb
  2213. @@:
  2214.         pop     edi ecx
  2215. ; copy new data
  2216.         mov     eax, edx
  2217.         neg     ebx
  2218.         jecxz   @f
  2219.         lea     ebx, [ebp+FAT.buffer+0x200+ebx]
  2220.         call    memmove
  2221.         xor     ebx, ebx
  2222. @@:
  2223.         pop     eax
  2224. ; save sector
  2225.         push    ebx
  2226.         lea     ebx, [ebp+FAT.buffer]
  2227.         call    fs_write32_app
  2228.         pop     ebx
  2229.         test    eax, eax
  2230.         jnz     .device_err2
  2231.         add     edx, ecx
  2232.         sub     [esp], ecx
  2233.         pop     ecx
  2234.         jz      .ret
  2235. .skip:
  2236. ; next sector
  2237.         pop     eax
  2238.         inc     eax
  2239.         push    eax
  2240.         cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2241.         jb      @f
  2242.         and     dword [esp], 0
  2243.         mov     eax, edi
  2244.         call    get_FAT
  2245.         mov     edi, eax
  2246.         jc      .device_err
  2247.         cmp     edi, 2
  2248.         jb      .fat_err
  2249.         cmp     edi, [ebp+FAT.fatRESERVED]
  2250.         jae     .fat_err
  2251. @@:
  2252.         sub     esi, 0x200
  2253.         jae     @f
  2254.         xor     esi, esi
  2255. @@:
  2256.         sub     dword [esp+4], 0x200
  2257.         jae     @f
  2258.         and     dword [esp+4], 0
  2259. @@:
  2260.         jmp     .write_loop
  2261.  
  2262. hd_extend_file.zero_size:
  2263.         xor     eax, eax
  2264.         jmp     hd_extend_file.start_extend
  2265.  
  2266. ; extends file on hd to given size (new data area is undefined)
  2267. ; in: edi->direntry, ecx=new size
  2268. ; out: CF=0 => OK, eax=0
  2269. ;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or ERROR_DEVICE)
  2270. hd_extend_file:
  2271.         push    esi
  2272.         mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
  2273.         imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
  2274.         push    ecx
  2275. ; find the last cluster of file
  2276.         mov     eax, [edi+20-2]
  2277.         mov     ax, [edi+26]
  2278.         mov     ecx, [edi+28]
  2279.         jecxz   .zero_size
  2280. .last_loop:
  2281.         sub     ecx, esi
  2282.         jbe     .last_found
  2283.         call    get_FAT
  2284.         jnc     @f
  2285. .device_err:
  2286.         pop     ecx
  2287. .device_err2:
  2288.         pop     esi
  2289.         push    ERROR_DEVICE
  2290. .ret_err:
  2291.         pop     eax
  2292.         stc
  2293.         ret
  2294. @@:
  2295.         cmp     eax, 2
  2296.         jb      .fat_err
  2297.         cmp     eax, [ebp+FAT.fatRESERVED]
  2298.         jb      .last_loop
  2299. .fat_err:
  2300.         pop     ecx esi
  2301.         push    ERROR_FAT_TABLE
  2302.         jmp     .ret_err
  2303. .last_found:
  2304.         push    eax
  2305.         call    get_FAT
  2306.         jnc     @f
  2307.         pop     eax
  2308.         jmp     .device_err
  2309. @@:
  2310.         cmp     eax, [ebp+FAT.fatRESERVED]
  2311.         pop     eax
  2312.         jb      .fat_err
  2313. ; set length to full number of clusters
  2314.         sub     [edi+28], ecx
  2315. .start_extend:
  2316.         pop     ecx
  2317. ; now do extend
  2318.         push    edx
  2319.         mov     edx, 2          ; start scan from cluster 2
  2320. .extend_loop:
  2321.         cmp     [edi+28], ecx
  2322.         jae     .extend_done
  2323. ; add new cluster
  2324.         push    eax
  2325.         call    get_free_FAT
  2326.         jc      .disk_full
  2327.         mov     edx, [ebp+FAT.fatEND]
  2328.         call    set_FAT
  2329.         mov     edx, eax
  2330.         pop     eax
  2331.         test    eax, eax
  2332.         jz      .first_cluster
  2333.         push    edx
  2334.         call    set_FAT
  2335.         pop     edx
  2336.         jmp     @f
  2337. .first_cluster:
  2338.         ror     edx, 16
  2339.         mov     [edi+20], dx
  2340.         ror     edx, 16
  2341.         mov     [edi+26], dx
  2342. @@:
  2343.         push    ecx
  2344.         mov     ecx, -1
  2345.         call    add_disk_free_space
  2346.         pop     ecx
  2347.         mov     eax, edx
  2348.         add     [edi+28], esi
  2349.         jmp     .extend_loop
  2350. .extend_done:
  2351.         mov     [edi+28], ecx
  2352.         pop     edx esi
  2353.         xor     eax, eax        ; CF=0
  2354.         ret
  2355. .device_err3:
  2356.         pop     edx
  2357.         jmp     .device_err2
  2358. .disk_full:
  2359.         pop     eax edx esi
  2360.         movi    eax, ERROR_DISK_FULL
  2361.         stc
  2362.         ret
  2363.  
  2364. ;----------------------------------------------------------------
  2365. ;
  2366. ;  fs_HdSetFileEnd - set end of file on hard disk
  2367. ;
  2368. ;  Obsolete, will be replaced with filesystem-specific functions.
  2369. ;
  2370. ;  esi  points to filename
  2371. ;  ebx  points to 64-bit number = new file size
  2372. ;  ecx  ignored (reserved)
  2373. ;  edx  ignored (reserved)
  2374. ;
  2375. ;  ret eax = 0 ok or other = errormsg
  2376. ;
  2377. ;--------------------------------------------------------------
  2378. fs_HdSetFileEnd:
  2379.         cmp     [fs_type], 16
  2380.         jz      @f
  2381.         cmp     [fs_type], 32
  2382.         jz      @f
  2383.         cmp     [fs_type], 1
  2384.         jz      ntfs_HdSetFileEnd
  2385.         cmp     [fs_type], 2
  2386.         jz      ext2_HdSetFileEnd
  2387.         movi    eax, ERROR_UNKNOWN_FS
  2388.         ret
  2389. @@:
  2390.         sub     ebx, 4
  2391.         push    ebp
  2392.         mov     ebp, [fs_dependent_data_start.partition]
  2393.         call    fat_SetFileEnd
  2394.         pop     ebp
  2395.         ret
  2396.  
  2397. ;----------------------------------------------------------------
  2398. ; fat_SetFileEnd - FAT16/32 implementation of setting end-of-file
  2399. ; in:  ebp = pointer to FAT structure
  2400. ; in:  esi+[esp+4] = name
  2401. ; in:  ebx = pointer to parameters from sysfunc 70
  2402. ; out: eax, ebx = return values for sysfunc 70
  2403. ;----------------------------------------------------------------
  2404. fat_SetFileEnd:
  2405.         call    fat_lock
  2406.         push    edi
  2407.         cmp     byte [esi], 0
  2408.         jnz     @f
  2409. .access_denied:
  2410.         push    ERROR_ACCESS_DENIED
  2411. .ret:
  2412.         call    fat_unlock
  2413.         pop     eax
  2414.         pop     edi
  2415.         ret
  2416. @@:
  2417.         stdcall hd_find_lfn, [esp+4+4]
  2418.         jnc     @f
  2419. .reteax:
  2420.         push    eax
  2421.         jmp     .ret
  2422. @@:
  2423. ; must not be directory
  2424.         test    byte [edi+11], 10h
  2425.         jnz     .access_denied
  2426. ; file size must not exceed 4 Gb
  2427.         cmp     dword [ebx+8], 0
  2428.         jz      @f
  2429.         push    ERROR_END_OF_FILE
  2430.         jmp     .ret
  2431. @@:
  2432.         push    eax     ; save directory sector
  2433. ; set file modification date/time to current
  2434.         call    fat_update_datetime
  2435.         mov     eax, [ebx+4]
  2436.         cmp     eax, [edi+28]
  2437.         jb      .truncate
  2438.         ja      .expand
  2439.         pop     eax
  2440.         lea     ebx, [ebp+FAT.buffer]
  2441.         call    fs_write32_sys
  2442.         test    eax, eax
  2443.         jz      @f
  2444.         push    ERROR_DEVICE
  2445.         jmp     .ret
  2446. @@:
  2447.         push    0
  2448.         jmp     .ret
  2449. .expand:
  2450.         push    ebx ebp ecx
  2451.         push    dword [edi+28]  ; save old size
  2452.         mov     ecx, eax
  2453.         call    hd_extend_file
  2454.         push    eax             ; return code
  2455.         jnc     .expand_ok
  2456.         cmp     al, ERROR_DISK_FULL
  2457.         jz      .disk_full
  2458. .pop_ret:
  2459.         call    update_disk
  2460.         pop     eax ecx ecx ebp ebx ecx
  2461.         jmp     .reteax
  2462. .expand_ok:
  2463. .disk_full:
  2464. ; save directory
  2465.         mov     eax, [edi+28]
  2466.         xchg    eax, [esp+20]
  2467.         lea     ebx, [ebp+FAT.buffer]
  2468.         call    fs_write32_sys
  2469.         test    eax, eax
  2470.         mov     eax, [edi+20-2]
  2471.         mov     ax, [edi+26]
  2472.         mov     edi, eax
  2473.         jz      @f
  2474. .pop_ret11:
  2475.         mov     byte [esp], ERROR_DEVICE
  2476.         jmp     .pop_ret
  2477. @@:
  2478.         test    edi, edi
  2479.         jz      .pop_ret
  2480. ; now zero new data
  2481.         push    0
  2482. ; edi=current cluster, [esp]=sector in cluster
  2483. ; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
  2484. .zero_loop:
  2485.         cmp     edi, 2
  2486.         jb      .error_fat
  2487.         cmp     edi, [ebp+FAT.fatRESERVED]
  2488.         jae     .error_fat
  2489.         sub     dword [esp+8], 0x200
  2490.         jae     .next_cluster
  2491.         lea     eax, [edi-2]
  2492.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2493.         add     eax, [ebp+FAT.DATA_START]
  2494.         add     eax, [esp]
  2495.         cmp     dword [esp+8], -0x200
  2496.         jz      .noread
  2497.         push    eax
  2498.         lea     ebx, [ebp+FAT.buffer]
  2499.         call    fs_read32_app
  2500.         test    eax, eax
  2501.         pop     eax
  2502.         jnz     .err_next
  2503. .noread:
  2504.         mov     ecx, [esp+8]
  2505.         neg     ecx
  2506.         push    edi
  2507.         lea     edi, [ebp+FAT.buffer+0x200]
  2508.         add     edi, [esp+12]
  2509.         push    eax
  2510.         xor     eax, eax
  2511.         mov     [esp+16], eax
  2512.         rep stosb
  2513.         pop     eax
  2514.         pop     edi
  2515.         call    fs_write32_app
  2516.         test    eax, eax
  2517.         jz      .next_cluster
  2518. .err_next:
  2519.         mov     byte [esp+4], ERROR_DEVICE
  2520. .next_cluster:
  2521.         pop     eax
  2522.         sub     dword [esp+20], 0x200
  2523.         jbe     .pop_ret
  2524.         inc     eax
  2525.         push    eax
  2526.         cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2527.         jb      .zero_loop
  2528.         and     dword [esp], 0
  2529.         mov     eax, edi
  2530.         call    get_FAT
  2531.         mov     edi, eax
  2532.         jnc     .zero_loop
  2533.         pop     eax
  2534.         jmp     .pop_ret11
  2535. .truncate:
  2536.         mov     [edi+28], eax
  2537.         push    ecx
  2538.         mov     ecx, [edi+20-2]
  2539.         mov     cx, [edi+26]
  2540.         push    eax
  2541.         test    eax, eax
  2542.         jz      .zero_size
  2543. ; find new last cluster
  2544. @@:
  2545.         cmp     ecx, 2
  2546.         jb      .error_fat2
  2547.         cmp     ecx, [ebp+FAT.fatRESERVED]
  2548.         jae     .error_fat2
  2549.         mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2550.         shl     eax, 9
  2551.         sub     [esp], eax
  2552.         jbe     @f
  2553.         mov     eax, ecx
  2554.         call    get_FAT
  2555.         mov     ecx, eax
  2556.         jnc     @b
  2557. .device_err3:
  2558.         pop     eax ecx eax edi
  2559.         call    update_disk
  2560.         call    fat_unlock
  2561.         movi    eax, ERROR_DEVICE
  2562.         ret
  2563. @@:
  2564. ; we will zero data at the end of last sector - remember it
  2565.         push    ecx
  2566. ; terminate FAT chain
  2567.         push    edx
  2568.         mov     eax, ecx
  2569.         mov     edx, [ebp+FAT.fatEND]
  2570.         call    set_FAT
  2571.         mov     eax, edx
  2572.         pop     edx
  2573.         jnc     @f
  2574. .device_err4:
  2575.         pop     ecx
  2576.         jmp     .device_err3
  2577. .zero_size:
  2578.         and     word [edi+20], 0
  2579.         and     word [edi+26], 0
  2580.         push    0
  2581.         mov     eax, ecx
  2582. @@:
  2583. ; delete FAT chain
  2584.         call    clear_cluster_chain
  2585.         jc      .device_err4
  2586. ; save directory
  2587.         mov     eax, [esp+12]
  2588.         push    ebx
  2589.         lea     ebx, [ebp+FAT.buffer]
  2590.         call    fs_write32_sys
  2591.         pop     ebx
  2592.         test    eax, eax
  2593.         jnz     .device_err4
  2594. ; zero last sector, ignore errors
  2595.         pop     ecx
  2596.         pop     eax
  2597.         dec     ecx
  2598.         imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2599.         add     ecx, [ebp+FAT.DATA_START]
  2600.         push    eax
  2601.         sar     eax, 9
  2602.         add     ecx, eax
  2603.         pop     eax
  2604.         and     eax, 0x1FF
  2605.         jz      .truncate_done
  2606.         push    ebx eax
  2607.         mov     eax, ecx
  2608.         lea     ebx, [ebp+FAT.buffer]
  2609.         call    fs_read32_app
  2610.         pop     eax
  2611.         lea     edi, [ebp+FAT.buffer+eax]
  2612.         push    ecx
  2613.         mov     ecx, 0x200
  2614.         sub     ecx, eax
  2615.         xor     eax, eax
  2616.         rep stosb
  2617.         pop     eax
  2618.         call    fs_write32_app
  2619.         pop     ebx
  2620. .truncate_done:
  2621.         pop     ecx eax edi
  2622.         call    update_disk
  2623.         call    fat_unlock
  2624.         xor     eax, eax
  2625.         ret
  2626. .error_fat:
  2627.         pop     eax
  2628.         mov     byte [esp], ERROR_FAT_TABLE
  2629.         jmp     .pop_ret
  2630. .error_fat2:
  2631.         pop     eax ecx eax edi
  2632.         call    update_disk
  2633.         call    fat_unlock
  2634.         movi    eax, ERROR_FAT_TABLE
  2635.         ret
  2636.  
  2637. fs_HdGetFileInfo:
  2638.         cmp     [fs_type], 16
  2639.         jz      @f
  2640.         cmp     [fs_type], 32
  2641.         jz      @f
  2642.         cmp     [fs_type], 1
  2643.         jz      ntfs_HdGetFileInfo
  2644.         cmp     [fs_type], 2
  2645.         jz      ext2_HdGetFileInfo
  2646.         mov     eax, ERROR_UNKNOWN_FS
  2647.         ret
  2648. @@:
  2649.         sub     ebx, 4
  2650.         push    ebp
  2651.         mov     ebp, [fs_dependent_data_start.partition]
  2652.         call    fat_GetFileInfo
  2653.         pop     ebp
  2654.         ret
  2655.  
  2656. ;----------------------------------------------------------------
  2657. ; fat_GetFileInfo - FAT16/32 implementation of getting file info
  2658. ; in:  ebp = pointer to FAT structure
  2659. ; in:  esi+[esp+4] = name
  2660. ; in:  ebx = pointer to parameters from sysfunc 70
  2661. ; out: eax, ebx = return values for sysfunc 70
  2662. ;----------------------------------------------------------------
  2663. fat_GetFileInfo:
  2664.         cmp     byte [esi], 0
  2665.         jnz     @f
  2666.         mov     eax, 2
  2667.         ret
  2668. @@:
  2669.         push    edi
  2670.         call    fat_lock
  2671.         stdcall hd_find_lfn, [esp+4+4]
  2672.         jc      .error
  2673.         push    ebp
  2674.         xor     ebp, ebp
  2675.         mov     esi, [ebx+16]
  2676.         mov     dword [esi+4], ebp
  2677.         call    fat_entry_to_bdfe2
  2678.         pop     ebp
  2679.         call    fat_unlock
  2680.         xor     eax, eax
  2681.         pop     edi
  2682.         ret
  2683. .error:
  2684.         push    eax
  2685.         call    fat_unlock
  2686.         pop     eax
  2687.         pop     edi
  2688.         ret
  2689.  
  2690. fs_HdSetFileInfo:
  2691.         cmp     [fs_type], 16
  2692.         jz      @f
  2693.         cmp     [fs_type], 32
  2694.         jz      @f
  2695.         cmp     [fs_type], 1
  2696.         jz      ntfs_HdSetFileInfo
  2697.         cmp     [fs_type], 2
  2698.         jz      ext2_HdSetFileInfo
  2699.         mov     eax, ERROR_UNKNOWN_FS
  2700.         ret
  2701. @@:
  2702.         sub     ebx, 4
  2703.         push    ebp
  2704.         mov     ebp, [fs_dependent_data_start.partition]
  2705.         call    fat_SetFileInfo
  2706.         pop     ebp
  2707.         ret
  2708.  
  2709. ;----------------------------------------------------------------
  2710. ; fat_SetFileInfo - FAT16/32 implementation of setting file info
  2711. ; in:  ebp = pointer to FAT structure
  2712. ; in:  esi+[esp+4] = name
  2713. ; in:  ebx = pointer to parameters from sysfunc 70
  2714. ; out: eax, ebx = return values for sysfunc 70
  2715. ;----------------------------------------------------------------
  2716. fat_SetFileInfo:
  2717.         cmp     byte [esi], 0
  2718.         jnz     @f
  2719.         mov     eax, 2
  2720.         ret
  2721. @@:
  2722.         push    edi
  2723.         call    fat_lock
  2724.         stdcall hd_find_lfn, [esp+4+4]
  2725.         jc      .error
  2726.         push    eax
  2727.         mov     edx, [ebx+16]
  2728.         call    bdfe_to_fat_entry
  2729.         pop     eax
  2730.         lea     ebx, [ebp+FAT.buffer]
  2731.         call    fs_write32_sys
  2732.         call    update_disk
  2733.         call    fat_unlock
  2734.         pop     edi
  2735.         xor     eax, eax
  2736.         ret
  2737. .error:
  2738.         push    eax
  2739.         call    fat_unlock
  2740.         pop     eax
  2741.         pop     edi
  2742.         ret
  2743.  
  2744. ;----------------------------------------------------------------
  2745. ;
  2746. ;  fs_HdDelete - delete file or empty folder from hard disk
  2747. ;
  2748. ;  Obsolete, will be replaced with filesystem-specific functions.
  2749. ;
  2750. ;  esi  points to filename
  2751. ;
  2752. ;  ret  eax = 0 ok or other = errormsg
  2753. ;
  2754. ;--------------------------------------------------------------
  2755. fs_HdDelete:
  2756.         cmp     [fs_type], 16
  2757.         jz      @f
  2758.         cmp     [fs_type], 32
  2759.         jz      @f
  2760.         cmp     [fs_type], 1
  2761.         jz      ntfs_HdDelete
  2762.         cmp     [fs_type], 2
  2763.         jz      ext2_HdDelete
  2764.         movi    eax, ERROR_UNKNOWN_FS
  2765.         ret
  2766. @@:
  2767.         sub     ebx, 4
  2768.         push    ebp
  2769.         mov     ebp, [fs_dependent_data_start.partition]
  2770.         call    fat_Delete
  2771.         pop     ebp
  2772.         ret
  2773.  
  2774. ;----------------------------------------------------------------
  2775. ; fat_Delete - FAT16/32 implementation of deleting a file/folder
  2776. ; in:  ebp = pointer to FAT structure
  2777. ; in:  esi+[esp+4] = name
  2778. ; in:  ebx = pointer to parameters from sysfunc 70
  2779. ; out: eax, ebx = return values for sysfunc 70
  2780. ;----------------------------------------------------------------
  2781. fat_Delete:
  2782.         call    fat_lock
  2783.         cmp     byte [esi], 0
  2784.         jnz     @f
  2785. ; cannot delete root!
  2786. .access_denied:
  2787.         push    ERROR_ACCESS_DENIED
  2788. .pop_ret:
  2789.         call    fat_unlock
  2790.         pop     eax
  2791.         xor     ebx, ebx
  2792.         ret
  2793. @@:
  2794.         and     [ebp+FAT.longname_sec1], 0
  2795.         and     [ebp+FAT.longname_sec2], 0
  2796.         push    edi
  2797.         stdcall hd_find_lfn, [esp+4+4]
  2798.         jnc     .found
  2799.         pop     edi
  2800.         push    ERROR_FILE_NOT_FOUND
  2801.         jmp     .pop_ret
  2802. .found:
  2803.         cmp     dword [edi], '.   '
  2804.         jz      .access_denied2
  2805.         cmp     dword [edi], '..  '
  2806.         jz      .access_denied2
  2807.         test    byte [edi+11], 10h
  2808.         jz      .dodel
  2809. ; we can delete only empty folders!
  2810.         pushad
  2811.         mov     esi, [edi+20-2]
  2812.         mov     si, [edi+26]
  2813.         xor     ecx, ecx
  2814.         lea     eax, [esi-2]
  2815.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2816.         add     eax, [ebp+FAT.DATA_START]
  2817.         lea     ebx, [ebp+FAT.buffer]
  2818.         call    fs_read32_sys
  2819.         test    eax, eax
  2820.         jnz     .err1
  2821.         lea     eax, [ebx+0x200]
  2822.         add     ebx, 2*0x20
  2823. .checkempty:
  2824.         cmp     byte [ebx], 0
  2825.         jz      .empty
  2826.         cmp     byte [ebx], 0xE5
  2827.         jnz     .notempty
  2828.         add     ebx, 0x20
  2829.         cmp     ebx, eax
  2830.         jb      .checkempty
  2831.         inc     ecx
  2832.         cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
  2833.         jb      @f
  2834.         mov     eax, esi
  2835.         call    get_FAT
  2836.         jc      .err1
  2837.         cmp     eax, 2
  2838.         jb      .error_fat
  2839.         cmp     eax, [ebp+FAT.fatRESERVED]
  2840.         jae     .empty
  2841.         mov     esi, eax
  2842.         xor     ecx, ecx
  2843. @@:
  2844.         lea     eax, [esi-2]
  2845.         imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
  2846.         add     eax, [ebp+FAT.DATA_START]
  2847.         add     eax, ecx
  2848.         lea     ebx, [ebp+FAT.buffer]
  2849.         call    fs_read32_sys
  2850.         test    eax, eax
  2851.         lea     eax, [ebx+0x200]
  2852.         jz      .checkempty
  2853. .err1:
  2854.         popad
  2855. .err2:
  2856.         pop     edi
  2857.         call    fat_unlock
  2858.         movi    eax, ERROR_DEVICE
  2859.         ret
  2860. .error_fat:
  2861.         popad
  2862.         pop     edi
  2863.         call    fat_unlock
  2864.         movi    eax, ERROR_FAT_TABLE
  2865.         ret
  2866. .notempty:
  2867.         popad
  2868. .access_denied2:
  2869.         pop     edi
  2870.         call    fat_unlock
  2871.         movi    eax, ERROR_ACCESS_DENIED
  2872.         ret
  2873. .empty:
  2874.         popad
  2875.         push    eax ebx
  2876.         lea     ebx, [ebp+FAT.buffer]
  2877.         call    fs_read32_sys
  2878.         test    eax, eax
  2879.         pop     ebx eax
  2880.         jnz     .err2
  2881. .dodel:
  2882.         push    eax
  2883.         mov     eax, [edi+20-2]
  2884.         mov     ax, [edi+26]
  2885.         xchg    eax, [esp]
  2886. ; delete folder entry
  2887.         mov     byte [edi], 0xE5
  2888. ; delete LFN (if present)
  2889. .lfndel:
  2890.         lea     edx, [ebp+FAT.buffer]
  2891.         cmp     edi, edx
  2892.         ja      @f
  2893.         cmp     [ebp+FAT.longname_sec2], 0
  2894.         jz      .lfndone
  2895.         push    [ebp+FAT.longname_sec2]
  2896.         push    [ebp+FAT.longname_sec1]
  2897.         pop     [ebp+FAT.longname_sec2]
  2898.         and     [ebp+FAT.longname_sec1], 0
  2899.         push    ebx
  2900.         mov     ebx, edx
  2901.         call    fs_write32_sys
  2902.         mov     eax, [esp+4]
  2903.         call    fs_read32_sys
  2904.         pop     ebx
  2905.         pop     eax
  2906.         lea     edi, [ebp+FAT.buffer+0x200]
  2907. @@:
  2908.         sub     edi, 0x20
  2909.         cmp     byte [edi], 0xE5
  2910.         jz      .lfndone
  2911.         cmp     byte [edi+11], 0xF
  2912.         jnz     .lfndone
  2913.         mov     byte [edi], 0xE5
  2914.         jmp     .lfndel
  2915. .lfndone:
  2916.         push    ebx
  2917.         lea     ebx, [ebp+FAT.buffer]
  2918.         call    fs_write32_sys
  2919.         pop     ebx
  2920. ; delete FAT chain
  2921.         pop     eax
  2922.         call    clear_cluster_chain
  2923.         call    update_disk
  2924.         call    fat_unlock
  2925.         pop     edi
  2926.         xor     eax, eax
  2927.         ret
  2928.  
  2929. ; \end{diamond}
  2930.