Subversion Repositories Kolibri OS

Rev

Rev 7003 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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