Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 9754 → Rev 9755

/kernel/trunk/fs/exfat.inc
27,7 → 27,7
dd exFAT_GetFileInfo
dd exFAT_SetFileInfo
dd 0
dd 0 ;exFAT_Delete
dd exFAT_Delete
dd 0 ;exFAT_CreateFolder
dd 0 ;exFAT_Rename
exFAT_user_functions_end:
35,11 → 35,11
 
struct exFAT PARTITION
fat_change db ? ; 1=fat has changed
ClstHeap_change db ? ; 1=Cluster Heap has changed
createOption db ?
rb 2
Lock MUTEX ; currently operations with one partition
; can not be executed in parallel since the legacy code is not ready
fat_in_cache dd ?
FAT_START dd ? ; start of fat table
ROOT_START dd ? ; start of rootdir
SECTORS_PER_CLUSTER dd ?
57,11 → 57,12
fatStartScan dd ?
cluster_tmp dd ? ; used by analyze_directory and analyze_directory_to_write
ROOT_CLUSTER dd ? ; first rootdir cluster
fat_cache_ptr dd ?
points_to_BDFE dd ?
secondary_dir_entry dd ?
longname_sec1 dd ? ; used by analyze_directory to save 2 previous
longname_sec2 dd ? ; directory sectors for delete long filename
longname_sector1 dd ? ; used by analyze_directory to save 2 previous
longname_sector2 dd ? ; directory sectors for delete long filename
LFN_reserve_place dd ?
path_in_UTF8 dd ?
General_Sec_Flags dd ?
77,8 → 78,12
buff_file_dirsect dd ?
buff_file_dir_pos dd ?
fname_extdir_offset dd ?
fat_in_cache dd ?
fat_cache_ptr dd ?
ClstHeap_in_cache dd ?
ClstHeap_cache_ptr dd ?
volumeLabel rb 12
; The next nine areas (32*17) should be arranged sequentially.
; The next areas (32*19) should be arranged sequentially.
; Do not change their location!!!
file_dir_entry rb 32 ; Entry Type 0x85
str_ext_dir_entry rb 32 ; Entry Type 0xC0
299,11 → 304,14
; mov [ebp+FAT.fs_type], al
;------------------------------------------------------------------------------
; For FAT16 and FAT32, allocate 512 bytes for FAT cache.
mov eax, 512
; For exFAT allocate 512 bytes for Cluster Heap cache.
mov eax, 512*2
call malloc
test eax, eax
jz .free_return0
mov [ebp+exFAT.fat_cache_ptr], eax
add eax, 512
mov [ebp+exFAT.ClstHeap_cache_ptr], eax
; DEBUGF 1, "K : malloc exFAT.fat_cache_ptr EAX: %x\n", eax
 
mov eax, ebp
371,6 → 379,16
stc
ret
;--------------------------------------
.save_curr_sector_number:
mov eax, [ebp+exFAT.buffer_curr_sector]
cmp eax, [ebp+exFAT.longname_sector2]
je @f
push [ebp+exFAT.longname_sector2]
pop [ebp+exFAT.longname_sector1]
mov [ebp+exFAT.longname_sector2], eax
@@:
ret
;--------------------------------------
.file_directory_entry:
; DEBUGF 1, "K : exFAT_get_name 0x85\n"
mov eax, [ebp+exFAT.buffer_curr_sector]
381,6 → 399,8
mov [ebp+exFAT.fname_extdir_offset], eax
 
xor eax, eax
mov [ebp+exFAT.longname_sector1], eax
mov [ebp+exFAT.longname_sector2], eax
mov [ebp+exFAT.hash_flag], eax ; dword 0
mov al, byte [edi+1] ; Number of Secondary directory entries
dec eax
393,6 → 413,7
.stream_extension_directory_entry:
; DEBUGF 1, "K : exFAT_get_name 0xC0\n"
; DEBUGF 1, "K : exFAT SEDE need_hash :%x\n", [ebp+exFAT.need_hash]
call .save_curr_sector_number
mov eax, [ebp+exFAT.need_hash]
test eax, eax
jz .stream_extension_directory_entry_1 ; @f
441,7 → 462,7
; mov ebp,[esp+12+8+4+4+7*4+262*2+4+4]
; DEBUGF 1, "K : exFAT_get_name.longname Input FS EBP:%x\n", ebp
; pop ebp
call .save_curr_sector_number
mov eax, [ebp+exFAT.hash_flag]
test eax, eax
jnz .no
655,6 → 676,51
; DEBUGF 1, "K : exFAT write date: %x\n", ax
ret
;------------------------------------------------------------------------------
exFAT_set_FAT:
; in: eax = cluster, edx = value to save
; out: edx = old value, CF=1 -> error
push eax ebx esi
cmp eax, 2
jc .ret
cmp [ebp+exFAT.LAST_CLUSTER], eax
jc .ret
add eax, eax
@@:
add eax, eax
mov esi, 511
and esi, eax
shr eax, 9
add eax, [ebp+exFAT.FAT_START]
mov ebx, [ebp+exFAT.fat_cache_ptr]
cmp eax, [ebp+exFAT.fat_in_cache]
je .inCache
cmp [ebp+exFAT.fat_change], 0
je @f
call exFAT_write_fat_sector
@@:
mov [ebp+exFAT.fat_in_cache], eax
call fs_read32_sys
test eax, eax
jne .error
.inCache:
mov eax, [ebp+exFAT.fatMASK]
and edx, eax
xor eax, -1 ; mask for high bits
and eax, [ebx+esi] ; get high 4 bits
or eax, edx
mov edx, [ebx+esi] ; get old value
mov [ebx+esi], eax ; save new value
.write:
mov [ebp+exFAT.fat_change], 1
and edx, [ebp+exFAT.fatMASK]
.ret:
pop esi ebx eax
ret
 
.error:
stc
jmp .ret
;------------------------------------------------------------------------------
exFAT_get_FAT:
; DEBUGF 1, "K : exFAT_get_FAT \n"
; in: eax = cluster
677,7 → 743,7
je .inCache
cmp [ebp+exFAT.fat_change], 0
je @f
; call write_fat_sector
call exFAT_write_fat_sector
@@:
mov [ebp+exFAT.fat_in_cache], eax
call fs_read32_sys
735,9 → 801,11
cmp byte [esi], 0
jz .found
; test byte [edi+11], 10h
push eax
lea eax, [ebp+exFAT.file_dir_entry]
; DEBUGF 1, "K : exFAT_hd_find_lfn exFAT.file_dir_entry [EAX]: %x\n", [eax]
test byte [eax+4], 10000b
pop eax
jz .notfound
and dword [esp+12], 0
; this entry’s first cluster number
765,7 → 833,7
jmp .loop
 
.notfound:
; DEBUGF 1, "K : exFAT_hd_find_lfn.notfound \n"
; DEBUGF 1, "K : exFAT_hd_find_lfn.notfound EAX:%x\n", eax
add esp, 16
pop edi esi
stc
952,16 → 1020,20
; DEBUGF 1, "K : exFAT General_Sec_Flags %x\n", [ebp+exFAT.General_Sec_Flags]
; DEBUGF 1, "K : exFAT.valid_data_length 2 %x\n", [ebp+exFAT.valid_data_length]
cmp [ebp+exFAT.valid_data_length], 0
jbe @f
 
jbe .error
; DEBUGF 1, "K : exFAT_find_lfn call dword[eax-8] ; exFAT_notroot_next: \n"
call dword[eax-8] ; exFAT_notroot_next
jnc .l1
@@:
; DEBUGF 1, "K : exFAT_find_lfn.@@: \n"
add esp, 262*2
.reterr:
; DEBUGF 1, "K : exFAT_find_lfn.reterr \n"
stc
ret
.error:
movi eax, ERROR_FILE_NOT_FOUND
jmp @b
;------------------------------------------------------------------------------
exFAT_ReadFile:
; DEBUGF 1, "K : exFAT_ReadFile \n"
1648,7 → 1720,10
add ebx, 512
push eax
.l1:
; DEBUGF 1, "K : exFAT_ReadFolder.l1 \n"
; cmp [edi], dword 0
; je .l1_1
; DEBUGF 1, "K : exFAT_ReadFolder.l1 [EDI]:%x\n", [edi]
;.l1_1:
; push esi
; lea esi, [esp+20]
; DEBUGF 1, "K : exFAT RD need_hash :%x\n", [ebp+exFAT.need_hash]
1982,6 → 2057,280
pop eax
ret
;------------------------------------------------------------------------------
exFAT_Delete:
; DEBUGF 1, "K : exFAT_Delete\n"
; DEBUGF 1, "K : exFAT F70 +00: %x\n", [ebx]
; DEBUGF 1, "K : exFAT F70 +04: %x\n", [ebx+4]
; DEBUGF 1, "K : exFAT F70 +08: %x\n", [ebx+8]
; DEBUGF 1, "K : exFAT F70 +12: %x\n", [ebx+12]
; DEBUGF 1, "K : exFAT F70 +16: %x\n", [ebx+16]
; DEBUGF 1, "K : exFAT F70 +20: %x\n", [ebx+20]
; DEBUGF 1, "K : exFAT Path: %s\n", esi
call exFAT_lock
xor eax, eax
mov [ebp+exFAT.need_hash], eax ; dword 0
mov [ebp+exFAT.hash_flag], eax ; dword 0
; and [ebp+exFAT.longname_sec1], 0
; and [ebp+exFAT.longname_sec2], 0
mov [ebp+exFAT.longname_sec1], eax
mov [ebp+exFAT.longname_sec2], eax
call exFAT_hd_find_lfn
jc .notFound
; cmp dword [edi], '. '
; jz .access_denied2
; cmp dword [edi], '.. '
; jz .access_denied2
; test byte [edi+11], 10h
push eax
lea eax, [ebp+exFAT.file_dir_entry]
; DEBUGF 1, "K : exFAT_Delete: File Attributes:%x\n", [eax+4]
test byte [eax+4], 10000b
pop eax
jz .dodel
; we can delete only empty folders!
pushad
; mov esi, [edi+20-2]
; mov si, [edi+26] ; esi=cluster
lea eax, [ebp+exFAT.str_ext_dir_entry]
mov esi, [eax+20] ; cluster
; DEBUGF 1, "K : exFAT_Delete: Cluster1:%x [EDI+20]:%x\n", esi, [edi+20]
xor ecx, ecx
lea eax, [esi-2]
imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER]
add eax, [ebp+exFAT.DATA_START]
; add eax, [ebp+exFAT.CLUSTER_HEAP_START]
lea ebx, [ebp+exFAT.buffer]
call fs_read32_sys
test eax, eax
jnz .err1
lea eax, [ebx+0x200]
; add ebx, 2*0x20
.checkempty:
; DEBUGF 1, "K : exFAT_Delete.checkempty: [EBX]:%x\n", [ebx]
cmp byte [ebx], 0 ; DIR_Name[0] == 0x00, then the directory entry is free
jz .empty
; cmp byte [ebx], 0xE5 ; DIR_Name[0] == 0xE5, then the directory entry is free
; jnz .notempty
cmp byte [ebx], 0x85 ; File/Folder Directory Entry of ExFAT
jz .notempty
cmp byte [ebx], 0xC0 ; Stream Extension Directory Entry of ExFAT
jz .notempty
cmp byte [ebx], 0xC1 ; File Name Extension Directory Entry of ExFAT
jz .notempty
add ebx, 0x20
cmp ebx, eax
jb .checkempty
inc ecx
cmp ecx, [ebp+exFAT.SECTORS_PER_CLUSTER]
jb @f
mov eax, esi
; Check - General Secondary Flags
; Bit 0 : Allocation possible
; 0 – No cluster allocated; 1 – cluster allocation is possible
; Bit 1 : No FAT chain
; 0 – Yes ; The clusters of this file/directory are NOT contiguous
; 1 – No; The Contiguous Cluster are allocated to this file/directory;
; This improves the File read performance
; Bits 2 – 7 : Reserved
test byte [ebp+exFAT.General_Sec_Flags], 10b
jz .get_FAT
inc eax ; inc cluster
jmp .continue
.get_FAT:
; DEBUGF 1, "K : exFAT_Delete.get_FAT:\n"
call exFAT_get_FAT
jc .err1
cmp eax, 2
jb .error_fat
.continue:
; DEBUGF 1, "K : exFAT_Delete.continue:\n"
cmp eax, [ebp+exFAT.fatRESERVED]
jae .empty
mov esi, eax
xor ecx, ecx
@@:
; DEBUGF 1, "K : exFAT_Delete.@@:\n"
lea eax, [esi-2]
imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER]
add eax, [ebp+exFAT.DATA_START]
; add eax, [ebp+exFAT.CLUSTER_HEAP_START]
add eax, ecx
lea ebx, [ebp+exFAT.buffer]
call fs_read32_sys
test eax, eax
lea eax, [ebx+0x200]
jz .checkempty
.err1:
; DEBUGF 1, "K : exFAT_Delete.err1:\n"
popad
.err2:
; DEBUGF 1, "K : exFAT_Delete.err2:\n"
push ERROR_DEVICE
.ret:
; DEBUGF 1, "K : exFAT_Delete.ret:\n"
call exFAT_unlock
pop eax
ret
 
.notFound:
; DEBUGF 1, "K : exFAT_Delete.notFound:\n"
push ERROR_FILE_NOT_FOUND
jmp .ret
 
.error_fat:
; DEBUGF 1, "K : exFAT_Delete.error_fat:\n"
popad
push ERROR_FS_FAIL
jmp .ret
 
.notempty:
; DEBUGF 1, "K : exFAT_Delete.notempty:\n"
popad
.access_denied2:
; DEBUGF 1, "K : exFAT_Delete.access_denied2:\n"
push ERROR_ACCESS_DENIED
jmp .ret
 
.empty:
; DEBUGF 1, "K : exFAT_Delete.empty:\n"
popad
push eax ebx
lea ebx, [ebp+exFAT.buffer]
call fs_read32_sys
test eax, eax
pop ebx eax
jnz .err2
.dodel:
; DEBUGF 1, "K : exFAT_Delete.dodel:\n"
push eax
; mov eax, [edi+20-2]
; mov ax, [edi+26] ; eax=cluster
lea eax, [ebp+exFAT.str_ext_dir_entry]
mov eax, [eax+20] ; cluster
; DEBUGF 1, "K : exFAT_Delete: Cluster2:%x [EDI+20]:%x\n", eax, [edi+20]
xchg eax, [esp]
 
mov edi, [ebp+exFAT.buff_file_dir_pos]
cmp eax, [ebp+exFAT.buff_file_dirsect]
je .continue_2
 
mov eax, [ebp+exFAT.buff_file_dirsect]
mov [ebp+exFAT.buffer_curr_sector], eax
 
push eax ebx
lea ebx, [ebp+exFAT.buffer]
call fs_read32_sys
test eax, eax
jz .continue_1 ; CF=0
 
pop ebx
add esp, 4
jmp .err2
 
.continue_1:
; DEBUGF 1, "K : exFAT_Delete.continue_1:\n"
pop ebx eax
 
.continue_2:
; DEBUGF 1, "K : exFAT_Delete.continue_2: EAX:%x\n", eax
push ecx
; delete folder entry
; mov byte [edi], 0xE5 ; for FAT
and byte [edi], 0x7F ; Entry Type is 0x85 is changed to 0x05
movzx ecx, byte [edi+1] ; Number of Secondary directory entries
inc ecx
; delete LFN (if present)
.lfndel:
; DEBUGF 1, "K : exFAT_Delete.lfndel: [EDI]:%x\n", [edi]
add edi, 0x20
; lea edx, [ebp+exFAT.buffer]
lea edx, [ebp+exFAT.buffer+0x200]
; cmp edi, edx
cmp edx, edi
ja @f
 
; cmp [ebp+exFAT.longname_sec2], 0
; jz .lfndone
; push [ebp+exFAT.longname_sec2]
; push [ebp+exFAT.longname_sec1]
; pop [ebp+exFAT.longname_sec2]
; and [ebp+exFAT.longname_sec1], 0
; DEBUGF 1, "K : exFAT_Delete: lngnm_sec1:%x lngnm_sec2:%x\n", [ebp+exFAT.longname_sector1], [ebp+exFAT.longname_sector2]
cmp [ebp+exFAT.longname_sector1], 0
je .longname_sec2
 
push eax
mov eax, [ebp+exFAT.buff_file_dirsect]
cmp eax, [ebp+exFAT.longname_sector1]
pop eax
; je .longname_sec2
jne .longname_sec1
and [ebp+exFAT.longname_sector1], 0
jmp .longname_sec2
.longname_sec1:
push [ebp+exFAT.longname_sector1]
and [ebp+exFAT.longname_sector1], 0
jmp .longname_sec3
.longname_sec2:
; DEBUGF 1, "K : exFAT_Delete.longname_sec2:\n"
cmp [ebp+exFAT.longname_sector2], 0
je .lfndone
 
push eax
mov eax, [ebp+exFAT.buff_file_dirsect]
cmp eax, [ebp+exFAT.longname_sector2]
pop eax
je .lfndone
 
push [ebp+exFAT.longname_sector2]
and [ebp+exFAT.longname_sector2], 0
.longname_sec3:
; DEBUGF 1, "K : exFAT_Delete.longname_sec3:\n"
 
push ebx
; mov ebx, edx
lea ebx, [ebp+exFAT.buffer]
call fs_write32_sys
mov eax, [esp+4]
; DEBUGF 1, "K : exFAT_Delete: EAX:%x\n", eax
call fs_read32_sys
pop ebx
pop eax
; lea edi, [ebp+exFAT.buffer+0x200]
lea edi, [ebp+exFAT.buffer]
@@:
; DEBUGF 1, "K : exFAT_Delete.@@: [EDI]:%x\n", [edi]
; sub edi, 0x20
;; add edi, 0x20
; cmp byte [edi], 0xE5
; jz .lfndone
dec ecx
jz .lfndone
cmp byte [edi], 0
jz .lfndone
cmp byte [edi], 0x85
jz .lfndone
; cmp byte [edi+11], 0xF
; jnz .lfndone
; mov byte [edi], 0xE5
and byte [edi], 0x7F ; 0xC0 is changed to 0x40; 0xC1 is changed to 0x41
jmp .lfndel
.lfndone:
; DEBUGF 1, "K : exFAT_Delete.lfndone:\n"
pop ecx
push ebx
lea ebx, [ebp+exFAT.buffer]
call fs_write32_sys
pop ebx
; delete FAT chain
pop eax
call exFAT_clear_Cluster_Heap
call exFAT_clear_cluster_chain
call exFAT_update_disk
call exFAT_unlock
xor eax, eax
ret
;------------------------------------------------------------------------------
calculate_SetChecksum_field:
push ebx ecx edx esi edi
lea esi, [ebp+exFAT.file_dir_entry]
2037,11 → 2386,163
pop edi esi edx ecx ebx
ret
;------------------------------------------------------------------------------
exFAT_clear_Cluster_Heap:
; in: eax = first cluster
 
;ClstHeap_change db ? ; 1=Cluster Heap has changed
;ClstHeap_in_cache dd ?
;ClstHeap_cache_ptr dd ?
 
push eax ebx ecx edx esi
mov ebx, [ebp+exFAT.ClstHeap_cache_ptr]
push eax
lea eax, [ebp+exFAT.str_ext_dir_entry]
mov edx, [eax+12] ; high dword of real file size
; DEBUGF 1, "K : exFAT_clear_Cluster_Heap Hdword file size:%x\n", edx
mov eax, [eax+8] ; low dword of real file size
; DEBUGF 1, "K : exFAT_clear_Cluster_Heap Ldword file size:%x\n", eax
mov ecx, [ebp+exFAT.SECTORS_PER_CLUSTER]
; DEBUGF 1, "K : exFAT_clear_Cluster_Heap SECTORS_PER_CLUSTER:%x\n", ecx
shl ecx, 9
div ecx
test edx, edx
jz @f
inc eax
@@:
mov edx, eax
; DEBUGF 1, "K : exFAT_clear_Cluster_Heap number of clusters:%x\n", edx
pop eax
.start:
; DEBUGF 1, "K : exFAT_clear_Cluster_Heap current cluster:%x\n", eax
cmp eax, [ebp+exFAT.LAST_CLUSTER]
ja .exit
cmp eax, 2
jb .exit
cmp eax, [ebp+exFAT.ROOT_CLUSTER]
jz .exit
 
push eax
dec eax
dec eax
 
mov ecx, 7
and ecx, eax ; get offset of bits
; DEBUGF 1, "K : exFAT_clear_Cluster_Heap offset of bits:%x\n", ecx
shr eax, 3
 
mov esi, 511
and esi, eax ; get offset of bytes
; DEBUGF 1, "K : exFAT_clear_Cluster_Heap offset of bytes:%x\n", esi
shr eax, 9 ; get get offset of sectors
; DEBUGF 1, "K : exFAT_clear_Cluster_Heap offset of sectors:%x\n", eax
add eax, [ebp+exFAT.CLUSTER_HEAP_START]
; DEBUGF 1, "K : exFAT_clear_Cluster_Heap general offset:%x\n", eax
cmp eax, [ebp+exFAT.ClstHeap_in_cache]
je .inCache
 
cmp [ebp+exFAT.ClstHeap_change], 0
je @f
 
mov [ebp+exFAT.ClstHeap_change], 0
push eax
mov eax, [ebp+exFAT.ClstHeap_in_cache]
call fs_write32_sys
pop eax
@@:
mov [ebp+exFAT.ClstHeap_in_cache], eax
call fs_read32_sys
test eax, eax
jne .error
.inCache:
xor eax, eax
mov al, [ebx+esi] ; get Cluster_Heap old value
; DEBUGF 1, "K : exFAT Cluster_Heap old value:%x\n", eax
ror al, cl
and al, 0xfe ; reset bit
rol al, cl
mov [ebx+esi], al ; save Cluster_Heap new value
 
; DEBUGF 1, "K : exFAT Cluster_Heap new value:%x\n", eax
mov [ebp+exFAT.ClstHeap_change], 1
pop eax
; Check - General Secondary Flags
; Bit 0 : Allocation possible
; 0 – No cluster allocated; 1 – cluster allocation is possible
; Bit 1 : No FAT chain
; 0 – Yes ; The clusters of this file/directory are NOT contiguous
; 1 – No; The Contiguous Cluster are allocated to this file/directory;
; This improves the File read performance
; Bits 2 – 7 : Reserved
; DEBUGF 1, "K : exFAT General_Sec_Flags %x\n", [ebp+exFAT.General_Sec_Flags]
test byte [ebp+exFAT.General_Sec_Flags], 10b
jz .get_FAT
 
dec edx ; dec cluster counter
jz .exit
 
inc eax ; inc cluster
jmp .start
.get_FAT:
call exFAT_get_FAT
jc .ret
jmp .start
.error:
pop eax
stc
jmp .ret
.exit:
clc
.ret:
pop esi edx ecx ebx eax
ret
;------------------------------------------------------------------------------
exFAT_clear_cluster_chain:
; in: eax = first cluster
; DEBUGF 1, "K : exFAT_clear_cluster_chain: GSF:%x\n", [ebp+exFAT.General_Sec_Flags]
; Check - General Secondary Flags
; Bit 0 : Allocation possible
; 0 – No cluster allocated; 1 – cluster allocation is possible
; Bit 1 : No FAT chain
; 0 – Yes ; The clusters of this file/directory are NOT contiguous
; 1 – No; The Contiguous Cluster are allocated to this file/directory;
; This improves the File read performance
; Bits 2 – 7 : Reserved
test byte [ebp+exFAT.General_Sec_Flags], 10b
jz .set_FAT
ret
.set_FAT:
push eax edx
@@:
cmp eax, [ebp+exFAT.LAST_CLUSTER]
ja @f
cmp eax, 2
jb @f
cmp eax, [ebp+exFAT.ROOT_CLUSTER]
jz @f
xor edx, edx
call exFAT_set_FAT
jc .ret
 
mov eax, edx
jmp @b
@@:
clc
.ret:
pop edx eax
ret
;------------------------------------------------------------------------------
exFAT_update_disk:
cmp [ebp+exFAT.ClstHeap_change], 0
je @f
mov [ebp+exFAT.ClstHeap_change], 0
push eax ebx
mov eax, [ebp+exFAT.ClstHeap_in_cache]
mov ebx, [ebp+exFAT.ClstHeap_cache_ptr]
call fs_write32_sys
pop ebx eax
@@:
cmp [ebp+exFAT.fat_change], 0
jz .noChange
; cmp [ebp+FAT.fs_type], 12
; jz .fat12
call exFAT_write_fat_sector
.noChange:
mov esi, [ebp+PARTITION.Disk]