kolibrios/kernel/trunk/fs/exfat.inc

1805 lines
59 KiB
PHP
Raw Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2021-2022. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision$
; exFAT external functions
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> exFAT structure
; esi -> path string in UTF-8
; out:
; eax, ebx = return values for sysfunc 70
iglobal
align 4
exFAT_user_functions:
dd exFAT_free
dd (exFAT_user_functions_end - exFAT_user_functions - 4) / 4
dd exFAT_ReadFile
dd exFAT_ReadFolder
dd 0 ;exFAT_CreateFile
dd 0 ;exFAT_Write
dd 0 ;exFAT_SetFileEnd
dd exFAT_GetFileInfo
dd 0 ;exFAT_SetFileInfo
dd 0
dd 0 ;exFAT_Delete
dd 0 ;exFAT_CreateFolder
dd 0 ;exFAT_Rename
exFAT_user_functions_end:
endg
struct exFAT PARTITION
fat_change db ? ; 1=fat 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 ?
BYTES_PER_SECTOR dd ? ; Note: if BPS <> 512 need lots of changes
SECTORS_PER_FAT dd ?
NUMBER_OF_FATS dd ?
CLUSTER_HEAP_START dd ?
CLUSTER_COUNT dd ?
DATA_START dd ? ; start of data area (=first cluster 2)
LAST_CLUSTER dd ? ; last availabe cluster
fatRESERVED dd ?
fatBAD dd ?
fatEND dd ?
fatMASK dd ?
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
LFN_reserve_place dd ?
path_in_UTF8 dd ?
General_Sec_Flags dd ?
valid_data_length dd ?
RAX_high dd ?
RCX_high dd ?
RDX_high dd ?
RDI_high dd ?
volumeLabel rb 12
; The next two areas (32+32) 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
buffer rb 512
ends
; these labels are located before the main function to make
; most of jumps to these be short
exFAT_create_partition.free_return0:
mov eax, ebp
call free
pop ebp
; DEBUGF 1, "K : exFAT_create_partition.free_return0 EAX: %x\n", eax
exFAT_create_partition.return0:
xor eax, eax
; DEBUGF 1, "K : exFAT_create_partition.return0 EAX: %x\n", eax
ret
; Mount if it's a valid exFAT partition.
exFAT_create_partition:
; DEBUGF 1, "K : exFAT_create_partition EAX: %x\n", eax
; in:
; ebp -> PARTITION structure
; ebx -> boot sector
; ebx+512 -> buffer
; out:
; eax -> exFAT structure, 0 = not exFAT
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .return0
; DEBUGF 1, "K : exFAT DISK.MediaInfo.SectorSize=512\n"
; bootsector must have been successfully read
cmp dword [esp+4], 0
jnz .return0
; DEBUGF 1, "K : exFAT bootsector successfully read\n"
; offset +510 = bootsector signature must be correct
cmp word [ebx+0x1fe], 0xaa55
jnz .return0
; DEBUGF 1, "K : exFAT bootsector signature correct\n"
; offset +109 = sectors per cluster must be nonzero
cmp byte [ebx+0x6d], 0
jz .return0
; DEBUGF 1, "K : exFAT sectors per cluster = nonzero\n"
; offset +108 = bytes per sector must be 0x200
; (LEGACY! In the future, increase support to 4096)
; the value for exFAT is a power of 2
cmp byte [ebx+0x6c], 9
jnz .return0
; DEBUGF 1, "K : exFAT bytes per sector = 512\n"
; Test name = 'EXFAT '
cmp dword [ebx+3], 'EXFA'
jnz .return0
cmp dword [ebx+7], 'T '
jnz .return0
; DEBUGF 1, "K : exFAT Test name EXFAT = OK \n"
movi eax, sizeof.exFAT
call malloc
test eax, eax
jz .return0
; DEBUGF 1, "K : exFAT malloc sizeof.exFAT = OK \n"
mov ecx, dword [ebp+PARTITION.FirstSector]
mov dword [eax+exFAT.FirstSector], ecx
; DEBUGF 1, "K : exFAT PARTITION.FirstSector ECX: %x\n", ecx
mov ecx, dword [ebp+PARTITION.FirstSector+4]
mov dword [eax+exFAT.FirstSector+4], ecx
; DEBUGF 1, "K : exFAT PARTITION.FirstSector+4 ECX: %x\n", ecx
mov ecx, dword [ebp+PARTITION.Length]
mov dword [eax+exFAT.Length], ecx
; DEBUGF 1, "K : exFAT PARTITION.Length ECX: %x\n", ecx
mov ecx, dword [ebp+PARTITION.Length+4]
mov dword [eax+exFAT.Length+4], ecx
; DEBUGF 1, "K : exFAT PARTITION.Length+4 ECX: %x\n", ecx
mov ecx, [ebp+PARTITION.Disk]
mov [eax+exFAT.Disk], ecx
; DEBUGF 1, "K : exFAT PARTITION.Disk ECX: %x\n", ecx
mov [eax+exFAT.FSUserFunctions], exFAT_user_functions
or [eax+exFAT.fat_in_cache], -1
mov [eax+exFAT.fat_change], 0
push ebp
mov ebp, eax
lea ecx, [ebp+exFAT.Lock]
call mutex_init
; offset +80 = sectors reserved
mov eax, [ebx+0x50]
mov [ebp+exFAT.FAT_START], eax
; DEBUGF 1, "K : exFAT.FAT_START EAX: %x\n", eax
; offset +109 = sectors per cluster. This is power of 2; Minimal value is 1;
; 2^0 =1 sector (512 Bytes) and maximum 32 MB cluster size in bytes
movzx ecx, byte [ebx+0x6d]
mov eax, 1
shl eax, cl
mov [ebp+exFAT.SECTORS_PER_CLUSTER], eax
; DEBUGF 1, "K : exFAT.SECTORS_PER_CLUSTER EAX: %x\n", eax
; offset +108 = bytes per sector. This is power of 2; Minimal value is 9;
; 2^9 =512 Bytes and maximum 2^12 =4096 Bytes
movzx ecx, byte [ebx+0x6c] ; bytes per sector
mov eax, 1
shl eax, cl
mov [ebp+exFAT.BYTES_PER_SECTOR], eax
; DEBUGF 1, "K : exFAT.BYTES_PER_SECTOR EAX: %x\n", eax
;------------------------------------------------------------------------------
; movzx eax, word [ebx+0x11] ; count of rootdir entries (=0 fat32)
; shl eax, 5 ; mul 32
; dec ecx
; add eax, ecx ; round up if not equal count
; inc ecx ; bytes per sector
; xor edx, edx
; div ecx
; mov [ebp+FAT.ROOT_SECTORS], eax ; count of rootdir sectors
;------------------------------------------------------------------------------
; offset +84 = Size of FAT in sectors
mov eax, [ebx+0x54] ; sectors per fat
mov [ebp+exFAT.SECTORS_PER_FAT], eax
; DEBUGF 1, "K : exFAT.SECTORS_PER_FAT EAX: %x\n", eax
;------------------------------------------------------------------------------
; offset +88 = Starting sector of cluster heap
mov eax, [ebx+0x58] ; Cluster offset
mov [ebp+exFAT.CLUSTER_HEAP_START], eax
; DEBUGF 1, "K : exFAT.CLUSTER_HEAP_START EAX: %x\n", eax
;------------------------------------------------------------------------------
; offset +92 = Number of clusters
mov eax, [ebx+0x5c] ; Cluster count
mov [ebp+exFAT.CLUSTER_COUNT], eax
; DEBUGF 1, "K : exFAT.CLUSTER_COUNT EAX: %x\n", eax
;------------------------------------------------------------------------------
; offset +110 = Either 1 or 2; if TexFAT is supported then it will be 2
movzx eax, byte [ebx+0x6e] ; number of fats
mov [ebp+exFAT.NUMBER_OF_FATS], eax
; DEBUGF 1, "K : exFAT.NUMBER_OF_FATS EAX: %x\n", eax
mul [ebp+exFAT.SECTORS_PER_FAT]
; DEBUGF 1, "K : exFAT.SECTORS_PER_FAT mul EAX: %x\n", eax
; test edx, edx
; jnz .free_return0
add eax, [ebp+exFAT.FAT_START]
jc .free_return0
; mov [ebp+FAT.ROOT_START], eax ; rootdir = fat_start + fat_size * fat_count
; add eax, [ebp+FAT.ROOT_SECTORS] ; rootdir sectors should be 0 on fat32
; jc .free_return0
mov [ebp+exFAT.DATA_START], eax
; DEBUGF 1, "K : exFAT.DATA_START EAX: %x\n", eax
;------------------------------------------------------------------------------
; offset +72 = Total number of Sectors
mov eax, [ebx+0x48+4] ; total sector count high part
test eax, eax
jnz .free_return0 ; 32-BIT LIMIT - MODIFY LATER WITY RASP !!!
; DEBUGF 1, "K : exFAT Total number of Sectors+4 EAX: %x\n", eax
mov eax, [ebx+0x48] ; total sector count low part
; DEBUGF 1, "K : exFAT Total number of Sectors EAX: %x\n", eax
cmp dword [ebp+exFAT.Length+4], 0
jnz @f
; DEBUGF 1, "K : exFAT.Length+4 = 0\n"
cmp eax, dword [ebp+exFAT.Length]
ja .free_return0
; DEBUGF 1, "K : exFAT.Length >= Total number of Sectors\n"
@@:
mov dword [ebp+exFAT.Length], eax
and dword [ebp+exFAT.Length+4], 0
sub eax, [ebp+exFAT.DATA_START] ; eax = count of data sectors
jc .free_return0
; DEBUGF 1, "K : EAX - exFAT.DATA_START EAX: %x\n", eax
xor edx, edx
div [ebp+exFAT.SECTORS_PER_CLUSTER]
inc eax
mov [ebp+exFAT.LAST_CLUSTER], eax
; DEBUGF 1, "K : exFAT.LAST_CLUSTER EAX: %x\n", eax
dec eax ; cluster count
jz .free_return0
; DEBUGF 1, "K : exFAT.LAST_CLUSTER >= 2 EAX: %x\n",eax
mov [ebp+exFAT.fatStartScan], 2
; cmp eax, 0xfff5
; jb .fat16
;------------------------------------------------------------------------------
;.fat32:
; pusha
; lea esi, [ebx+71]
; lea edi, [ebp+exFAT.volumeLabel]
; movsd
; movsd
; movsd
; popa
;------------------------------------------------------------------------------
; offset +96 = First cluster of root directory
mov eax, [ebx+0x60] ; rootdir cluster
mov [ebp+exFAT.ROOT_CLUSTER], eax
; DEBUGF 1, "K : exFAT.ROOT_CLUSTER EAX: %x\n", eax
dec eax
dec eax
imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER]
add eax, [ebp+exFAT.CLUSTER_HEAP_START]
mov [ebp+exFAT.ROOT_START], eax
; DEBUGF 1, "K : exFAT.ROOT_START EAX: %x\n", eax
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; movzx eax, word [ebx+0x30]
; mov [ebp+FAT.ADR_FSINFO], eax
;------------------------------------------------------------------------------
; push ebx
; add ebx, 512
; call fs_read32_sys
; test eax, eax
; jnz @f
; mov eax, [ebx+0x1ec]
; cmp eax, -1
; jz @f
; mov [ebp+exFAT.fatStartScan], eax
;@@:
; pop ebx
;------------------------------------------------------------------------------
mov [ebp+exFAT.fatRESERVED], 0x0FFFFFF6
mov [ebp+exFAT.fatBAD], 0x0FFFFFF7
mov [ebp+exFAT.fatEND], 0x0FFFFFF8
mov [ebp+exFAT.fatMASK], 0x0FFFFFFF
;------------------------------------------------------------------------------
; mov al, 32
;.fat_not_12_finalize:
; mov [ebp+FAT.fs_type], al
;------------------------------------------------------------------------------
; For FAT16 and FAT32, allocate 512 bytes for FAT cache.
mov eax, 512
call malloc
test eax, eax
jz .free_return0
mov [ebp+exFAT.fat_cache_ptr], eax
; DEBUGF 1, "K : malloc exFAT.fat_cache_ptr EAX: %x\n", eax
mov eax, ebp
pop ebp
ret
;------------------------------------------------------------------------------
exFAT_free:
push eax
mov eax, [eax+exFAT.fat_cache_ptr]
; DEBUGF 1, "K : exFAT_free exFAT.fat_cache_ptr EAX: %x\n", eax
call free
pop eax
jmp free
;------------------------------------------------------------------------------
exFAT_lock:
; DEBUGF 1, "K : exFAT_lock \n"
lea ecx, [ebp+exFAT.Lock]
jmp mutex_lock
exFAT_unlock:
; DEBUGF 1, "K : exFAT_unlock \n"
lea ecx, [ebp+exFAT.Lock]
jmp mutex_unlock
;------------------------------------------------------------------------------
exFAT_get_name:
cmp byte [edi], 0
jz .no
; DEBUGF 1, "K : exFAT_get_name EDI:%x [EDI]:%x\n", edi, [edi]
; push ebp
; mov ebp,[esp+12+8+4+4+7*4+262*2+4+4]
; DEBUGF 1, "K : exFAT_get_name START Input FS EBP:%x\n", ebp
; pop ebp
; in: edi -> FAT entry, esi -> buffer for UTF-16 name
; out: CF=1 -> no valid entry
cmp byte [edi], 0x85 ; File/Folder Directory Entry of ExFAT
jz .file_directory_entry
cmp byte [edi], 0xC0 ; Stream Extension Directory Entry of ExFAT
jz .stream_extension_directory_entry
cmp byte [edi], 0xC1 ; File Name Extension Directory Entry of ExFAT
jz .longname
push edi esi
xchg esi, edi
; DEBUGF 1, "K : exFAT Volume label dword [ESI]: %x\n", [esi]
cmp byte [esi], 0x83 ; Indicates that the Volume label exists
jnz .no_label
.label:
; DEBUGF 1, "K : exFAT_get_name.label \n"
add esi, 2
lea edi, [ebp+exFAT.volumeLabel]
push ecx
mov ecx, 12
call UTF16to8_string
pop ecx
; push edi
; lea edi, [ebp+exFAT.volumeLabel]
; DEBUGF 1, "K : exFAT Volume label: %s\n", edi
; pop edi
.no_label:
; DEBUGF 1, "K : exFAT_get_name.no_label \n"
pop esi edi
.no:
; DEBUGF 1, "K : exFAT_get_name.no \n"
stc
ret
;--------------------------------------
.file_directory_entry:
movzx eax, byte [edi+1] ; Number of Secondary directory entries
dec eax
mov [ebp+exFAT.secondary_dir_entry], eax
lea esi, [ebp+exFAT.file_dir_entry]
; DEBUGF 1, "K : exFAT.file_dir_entry ESI: %x [ESI]: %x\n", esi, [esi]
jmp @f
;--------------------------------------
.stream_extension_directory_entry:
lea esi, [ebp+exFAT.str_ext_dir_entry]
; DEBUGF 1, "K : exFAT.str_ext_dir_entry ESI: %x [ESI]: %x\n", esi, [esi]
@@:
push edi
xchg esi, edi
movsd
movsd
movsd
movsd
movsd
movsd
movsd
movsd
pop edi
; lea esi, [esp+20]
mov esi, [ebp+exFAT.LFN_reserve_place]
mov word [esi+260*2], 0 ; force null-terminating for orphans
jmp .no
;--------------------------------------
.longname:
; push ebp
; mov ebp,[esp+12+8+4+4+7*4+262*2+4+4]
; DEBUGF 1, "K : exFAT_get_name.longname 0 Input FS EBP:%x\n", ebp
; pop ebp
; DEBUGF 1, "K : exFAT_get_name.longname \n"
; DEBUGF 1, "K : exFAT_get_name.longname EDI:%x [EDI]:%x ESI:%x [ESI]:%x EBP:%x NAME:%s\n", edi, [edi], esi, [esi], ebp, ebp
; copy name (15 chars in UTF-16)
; mov word [esi+260*2], 0 ; force null-terminating for orphans
; push ebp
; 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
push edi esi
xchg esi, edi
add esi, 2
movsd
movsd
movsd
movsd
movsd
movsd
movsd
movsw
; force null-terminating for incomplete name
xor eax, eax
stosw
pop esi edi
; push ebp
; mov ebp,[esp+12+8+4+4+7*4+262*2+4+4]
; DEBUGF 1, "K : exFAT_get_name.longname Output FS EBP:%x\n", ebp
; pop ebp
mov eax, [ebp+exFAT.secondary_dir_entry]
dec eax
mov [ebp+exFAT.secondary_dir_entry], eax
jz @f
add esi, 30
jmp .no
; test ax, ax
; jnz .no ; if this is not first entry, more processing required
@@:
; mov esi, [ebp+exFAT.LFN_reserve_place]
; DEBUGF 1, "K : exFAT_get_name.longname END \n"
ret
;------------------------------------------------------------------------------
exFAT_entry_to_bdfe:
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
mov eax, [ebp-4]
mov [esi+4], eax ; cp866/UNICODE name
exFAT_entry_to_bdfe2:
; movzx eax, byte [edi+11]
movzx eax, byte [edi+4]
mov [esi], eax ; attributes
; movzx eax, word [edi+14]
movzx eax, word [edi+8]
call fat_time_to_bdfe
mov [esi+8], eax ; creation time
; movzx eax, word [edi+16]
movzx eax, word [edi+8+2]
call fat_date_to_bdfe
mov [esi+12], eax ; creation date
; and dword [esi+16], 0 ; last access time is not supported on FAT
movzx eax, word [edi+16]
call fat_time_to_bdfe
mov [esi+16], eax ; last access time
; movzx eax, word [edi+18]
movzx eax, word [edi+16+2]
call fat_date_to_bdfe
mov [esi+20], eax ; last access date
; movzx eax, word [edi+22]
movzx eax, word [edi+12]
call fat_time_to_bdfe
mov [esi+24], eax ; last write time
; movzx eax, word [edi+24]
movzx eax, word [edi+12+2]
call fat_date_to_bdfe
mov [esi+28], eax ; last write date
mov al, [esi]
test al, 10000b
jz .file_size
xor eax, eax
mov [esi+32], eax ; file size (low dword)
mov [esi+36], eax ; file size (high dword)
jmp @f
.file_size:
mov eax, [edi+32+8]
mov [esi+32], eax ; file size (low dword)
mov eax, [edi+32+8+4]
mov [esi+36], eax ; file size (high dword)
@@:
test ebp, ebp
jz .ret
.copy_path:
add esi, 40
push edi esi
mov edi, esi
mov esi, ebp
cmp byte [ebp-4], 2
jz .utf16
cmp byte [ebp-4], 3
jz .utf8
@@:
lodsw
call uni2ansi_char
stosb
test al, al
jnz @b
pop esi edi
add esi, 264
.ret:
; DEBUGF 1, "K : exFAT_entry_to_bdfe +264 ESI:%x\n", esi
ret
.utf8:
push ecx
mov ecx, 519
call UTF16to8_string
pop ecx
jmp @f
.utf16:
lodsw
stosw
test eax, eax
jnz .utf16
@@:
pop esi edi
add esi, 520
; DEBUGF 1, "K : exFAT_entry_to_bdfe +520 ESI:%x\n", esi
ret
;------------------------------------------------------------------------------
exFAT_get_FAT:
; DEBUGF 1, "K : exFAT_get_FAT \n"
; in: eax = cluster
; out: eax = next cluster, CF=1 -> error
push ebx esi
; cmp [ebp+FAT.fs_type], 12
; je .FAT12
; cmp [ebp+FAT.fs_type], 16
; je @f
; add eax, eax
;@@:
; add eax, eax
shl eax, 2
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 write_fat_sector
@@:
mov [ebp+exFAT.fat_in_cache], eax
call fs_read32_sys
test eax, eax
jnz .error
.inCache:
; DEBUGF 1, "K : exFAT_get_FAT.inCache \n"
mov eax, [ebx+esi]
and eax, [ebp+exFAT.fatMASK]
.ret:
pop esi ebx
ret
.error:
; DEBUGF 1, "K : exFAT_get_FAT.error \n"
stc
jmp .ret
;------------------------------------------------------------------------------
exFAT_hd_find_lfn:
; DEBUGF 1, "K : exFAT_hd_find_lfn path ESI: %s\n", esi
; in: esi -> path string in UTF-8
; out: CF=1 - file not found, eax=error code
; else CF=0 and edi->direntry, eax=sector
push esi edi
push 0
push 0
push exFAT_notroot_first ; 0 ; fat1x_root_first
push exFAT_notroot_next ; 0 ; fat1x_root_next
mov eax, [ebp+exFAT.ROOT_CLUSTER]
; mov [ebp+exFAT.secondary_dir_entry], dword 1
; cmp [ebp+FAT.fs_type], 32
; jz .fat32
jmp @f ; .fat32
.loop:
and [ebp+exFAT.longname_sec1], 0
and [ebp+exFAT.longname_sec2], 0
; push ebp
; mov ebp,[esp+12+8+4+4+7*4]
; DEBUGF 1, "K : exFAT_find_lfn Input FS EBP:%x\n", ebp
; pop ebp
call exFAT_find_lfn
; push ebp
; mov ebp,[esp+12+8+4+4+7*4]
; DEBUGF 1, "K : exFAT_find_lfn Output FS EBP:%x\n", ebp
; pop ebp
jc .notfound
; DEBUGF 1, "K : exFAT_hd_find_lfn [ESI]: %x\n", [esi]
cmp byte [esi], 0
jz .found
; test byte [edi+11], 10h
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
jz .notfound
and dword [esp+12], 0
; this entrys first cluster number
; mov eax, [edi+20-2]
; mov ax, [edi+26] ; cluster
lea eax, [ebp+exFAT.str_ext_dir_entry]
mov eax, [eax+20] ; cluster
;.fat32:
@@:
; DEBUGF 1, "K : exFAT_hd_find_lfn exFAT cluster EAX: %x\n", eax
mov [esp+8], eax
; mov dword [esp+4], exFAT_notroot_first ; fat_notroot_first
; mov dword [esp], exFAT_notroot_next ; fat_notroot_next
jmp .loop
.notfound:
; DEBUGF 1, "K : exFAT_hd_find_lfn.notfound \n"
add esp, 16
pop edi esi
stc
ret
.found:
; DEBUGF 1, "K : exFAT_hd_find_lfn.found \n"
lea eax, [esp+8]
cmp dword [eax], 0
jz .root
call exFAT_get_sector
jmp .cmn
.root:
; DEBUGF 1, "K : exFAT_hd_find_lfn.found.root \n"
mov eax, [eax+4]
add eax, [ebp+exFAT.ROOT_START]
.cmn:
; DEBUGF 1, "K : exFAT_hd_find_lfn.found.cmn \n"
add esp, 20 ; CF=0
pop esi
ret
;------------------------------------------------------------------------------
exFAT_find_lfn:
; DEBUGF 1, "K : exFAT_find_lfn \n"
; in:
; esi -> path in UTF-8
; parameters in the stack
; out:
; esi -> next name in the path
; edi -> direntry
; CF=1 -> file not found, eax = error code
mov [ebp+exFAT.secondary_dir_entry], dword 1
lea eax, [esp+12]
call dword [eax-4]
jc .reterr
sub esp, 262*2 ; reserve place for LFN
; lea eax, [esp]
mov eax, esp
mov [ebp+exFAT.LFN_reserve_place], eax
mov [ebp+exFAT.path_in_UTF8], esi
.l1:
; push esi
; lea esi, [esp+4]
; mov esi, [ebp+exFAT.LFN_reserve_place]
; DEBUGF 1, "K : exFAT_find_lfn.exFAT_get_name \n"
; push ebp
; mov ebp,[esp+12+8+4+4+7*4+262*2+4]
; DEBUGF 1, "K : exFAT_get_name Input FS EBP:%x\n", ebp
; pop ebp
call exFAT_get_name
; mov [ebp+exFAT.LFN_reserve_place], esi
; pop esi
; push ebp
; mov ebp,[esp+12+8+4+4+7*4+262*2+4]
; DEBUGF 1, "K : exFAT_get_name Output FS EBP:%x\n", ebp
; pop ebp
jc .no
push eax
xor eax, eax
cmp [ebp+exFAT.secondary_dir_entry], eax
pop eax
jnz .no
push edi esi
mov esi, [ebp+exFAT.path_in_UTF8]
lea edi, [esp+8]
@@:
call utf8to16
call utf16toUpper
mov edx, eax
mov ax, [edi]
call utf16toUpper
cmp ax, dx
jnz .done
add edi, 2
test ax, ax
jnz @b
dec esi
pop eax edi
.found:
; DEBUGF 1, "K : exFAT_find_lfn.found \n"
add esp, 262*2
; if this is LFN entry, advance to true entry
; cmp byte [edi+11], 0xF
; jnz @f
xor eax, eax
cmp [ebp+exFAT.secondary_dir_entry], eax
jz @f
lea eax, [esp+12]
call dword[eax-8]
jc .reterr
@@:
; DEBUGF 1, "K : exFAT_find_lfn.OK \n"
xor eax, eax
ret
.done:
; DEBUGF 1, "K : exFAT_find_lfn.done \n"
cmp dx, '/'
jnz @f
test ax, ax
jnz @f
mov [esp], esi
@@:
pop esi edi
jz .found
.no:
; DEBUGF 1, "K : exFAT_find_lfn.no \n"
lea eax, [esp+262*2+12]
call dword[eax-8]
jnc .l1
add esp, 262*2
.reterr:
; DEBUGF 1, "K : exFAT_find_lfn.reterr \n"
stc
ret
;------------------------------------------------------------------------------
exFAT_ReadFile:
; DEBUGF 1, "K : exFAT_ReadFile \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
; push eax
; pushfd
; pop eax
; DEBUGF 1, "K : eFlags:%x\n",eax
; pop eax
; DEBUGF 1, "K : EAX:%x EBX:%x ECX:%x EDX:%x\n", eax, ebx, ecx, edx
; DEBUGF 1, "K : EBP:%x ESI:%x EDI:%x\n", ebp, esi, edi
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> exFAT structure
; esi -> path string in UTF-8
; out:
; eax, ebx = return values for sysfunc 70
call exFAT_lock
call exFAT_hd_find_lfn
jc .notFound
; test byte [edi+11], 0x10 ; do not allow read directories
; jnz .noaccess
lea eax, [ebp+exFAT.file_dir_entry]
test byte [eax+4], 10000b ; do not allow read directories
jnz .noaccess
; Rewrite code to work with more than 4 GB files !!!
; cmp dword [ebx+8], 0
; jnz .endOfFile
mov edx, [ebx+8] ; file offset high
; DEBUGF 1, "K : exFAT_ReadFile Hdword file offset EDX:%x\n", edx
mov [ebp+exFAT.RDX_high], edx
mov edx, [ebx+4] ; file offset low
; DEBUGF 1, "K : exFAT_ReadFile Ldword file offset EAX:%x\n", edx
mov ecx, [ebx+12] ; size
mov ebx, [ebx+16] ; buffer
push ebx
push 0
test ecx, ecx ; read size 0?
jz .done
; mov eax, [edi+28] ; real file size
lea eax, [ebp+exFAT.str_ext_dir_entry]
; DEBUGF 1, "K : exFAT 0xC0 +00: %x\n", [eax]
; DEBUGF 1, "K : exFAT 0xC0 +04: %x\n", [eax+4]
; DEBUGF 1, "K : exFAT 0xC0 +08: %x\n", [eax+8]
; DEBUGF 1, "K : exFAT 0xC0 +12: %x\n", [eax+12]
; DEBUGF 1, "K : exFAT 0xC0 +16: %x\n", [eax+16]
; DEBUGF 1, "K : exFAT 0xC0 +20: %x\n", [eax+20]
; DEBUGF 1, "K : exFAT 0xC0 +24: %x\n", [eax+24]
; DEBUGF 1, "K : exFAT 0xC0 +28: %x\n", [eax+28]
push eax
movzx eax, byte [eax+1]
mov [ebp+exFAT.General_Sec_Flags], eax
pop eax
push eax
mov eax, [eax+12] ; high dword of real file size
mov [ebp+exFAT.RAX_high], eax
; DEBUGF 1, "K : exFAT_ReadFile Hdword file size EAX:%x\n", eax
pop eax
mov eax, [eax+8] ; low dword of real file size
; DEBUGF 1, "K : exFAT_ReadFile Ldword file size EAX:%x\n", eax
; sub eax, edx ; low dword file size - file offset low = rest of file
; jb .fileEnd
sub eax, edx ; low dword file size - file offset low = rest of file
push eax
mov eax, [ebp+exFAT.RDX_high]
sbb [ebp+exFAT.RAX_high], eax
pop eax
jb .fileEnd
; DEBUGF 1, "K : exFAT_ReadFile Hdword rest of file RAX:%x\n", [ebp+exFAT.RAX_high]
; DEBUGF 1, "K : exFAT_ReadFile Ldword rest of file EAX:%x\n", eax
push eax
mov eax, [ebp+exFAT.RAX_high]
test eax, eax
pop eax
jnz @f
cmp eax, ecx ; rest of file - requested size
jae @f
; DEBUGF 1, "K : exFAT_ReadFile 6=EOF EAX:%x ECX:%x EDX:%x\n", eax, ecx, edx
mov ecx, eax
mov byte [esp], 6 ; 6 = end of file, EOF
@@:
lea eax, [ebp+exFAT.str_ext_dir_entry]
mov eax, [eax+20] ; cluster
; DEBUGF 1, "K : exFAT EAX:%x EBX:%x ECX:%x EDX:%x\n", eax, ebx, ecx, edx
; now eax=cluster, ebx=buffer for data, ecx=count, edx=position
mov edi, [ebp+exFAT.SECTORS_PER_CLUSTER]
shl edi, 9 ; bytes per cluster
@@:
cmp eax, 2
jb .fileEnd
.continue_1:
cmp eax, [ebp+exFAT.fatRESERVED]
jae .fileEnd
push eax
xor eax, eax
sub edx, edi ; file_offset_low - bytes per cluster
sbb [ebp+exFAT.RDX_high], eax
pop eax
jc @f
; push edi
; lea edi, [ebp+exFAT.file_dir_entry]
; 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 [edi+1], 11b
; pop edi
test byte [ebp+exFAT.General_Sec_Flags], 11b
jz .get_FAT_1
inc eax
jmp .continue_1
.get_FAT_1:
call exFAT_get_FAT
jc .noaccess2
jmp @b
.notFound:
; DEBUGF 1, "K : exFAT_ReadFile.notFound: \n"
push eax
jmp .ret
.noaccess:
; DEBUGF 1, "K : exFAT_ReadFile.noaccess \n"
push ERROR_ACCESS_DENIED
jmp .ret
.endOfFile:
; DEBUGF 1, "K : exFAT_ReadFile.endOfFile \n"
push ERROR_END_OF_FILE
.ret:
call exFAT_unlock
pop eax
xor ebx, ebx
; DEBUGF 1, "K : exFAT_ReadFile Return EBX:%x\n", ebx
ret
@@:
; DEBUGF 1, "K : exFAT_ReadFile CONTINUE cluster EAX:%x\n", eax
mov esi, eax
dec eax
dec eax
push ebx edx
xor edx, edx
; DEBUGF 1, "K : exFAT_ReadFile IMUL in EDX:%x EAX:%x\n", EDX, eax
imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER] ; Sector edx:eax
; DEBUGF 1, "K : exFAT_ReadFile IMUL out EDX:%x EAX:%x\n", EDX, eax
xor ebx, ebx
add eax, [ebp+exFAT.CLUSTER_HEAP_START]
adc edx, ebx
mov [ebp+exFAT.RAX_high], edx
pop edx ebx
; DEBUGF 1, "K : exFAT_ReadFile start sector RAX_H:%x EAX:%x RDX_H:%x EDX:%x EDI:%x\n", [ebp+exFAT.RAX_high], eax, [ebp+exFAT.RDX_high], edx, edi
push eax
xor eax, eax
add edx, edi ; file offset low + bytes per cluster
adc [ebp+exFAT.RDX_high], eax
pop eax
test edx, edx
jz .alignedCluster
mov edi, edx ; file offset low
push eax
mov eax, [ebp+exFAT.RDX_high]
mov [ebp+exFAT.RDI_high], eax
pop eax
; shr edi, 9
push ebx
mov ebx, [ebp+exFAT.RDI_high]
shrd edi, ebx, 5 ; /32
shr ebx, 5 ; /32
shrd edi, ebx, 4 ; /16
shr ebx, 4 ; /16
mov [ebp+exFAT.RDI_high], ebx
pop ebx
add eax, edi ; RFile_start_sector_low - file_sector_offset_low
push ebx
mov ebx, [ebp+exFAT.RDI_high]
adc [ebp+exFAT.RAX_high], ebx
pop ebx
and edx, 511
and dword [ebp+exFAT.RDX_high], 0
cmp ecx, 512
jc .sectorPiece
test edx, edx
jz .alignedSector
.sectorPiece:
; DEBUGF 1, "K : exFAT_ReadFile.sectorPiece \n"
push eax ebx ecx edx
lea ebx, [ebp+exFAT.buffer]
mov edx, [ebp+exFAT.RAX_high]
xor ecx, ecx
inc ecx
; DEBUGF 1, "K : exFAT fs_read64_app EDX:%x EAX:%x ECX:%x EBX:%x EBP:%x\n", edx, eax, ecx, ebx, ebp
; call fs_read32_app
call fs_read64_app
; DEBUGF 1, "K : exFAT fs_read64_app Output EAX:%x ECX:%x EBX:%x\n", eax, ecx, ebx
test eax, eax
; lea eax, [ebp+exFAT.buffer]
mov eax, ebx ; exFAT.buffer
pop edx ecx ebx
jne .noaccess3
; DEBUGF 1, "K : exFAT_ReadFile memmove(-1) EAX:%x EBX:%x ECX:%x EDX:%x\n", eax, ebx, ecx, edx
add eax, edx ; exFAT.buffer + offset within a sector
push ecx
add ecx, edx ; requested size + offset within a sector
cmp ecx, 512
jbe @f
mov ecx, 512
@@:
sub ecx, edx ; requested size - offset within a sector
; DEBUGF 1, "K : exFAT_ReadFile memmove EAX:%x EBX:%x ECX:%x\n", eax, ebx, ecx
; eax = from
; ebx = to
; ecx = no of bytes
call memmove
; DEBUGF 1, "K : exFAT_ReadFile memmove(1) EAX:%x EBX:%x ECX:%x\n", eax, ebx, ecx
sub [esp], ecx
add ebx, ecx
; DEBUGF 1, "K : exFAT_ReadFile memmove(2) EAX:%x EBX:%x ECX:%x\n", eax, ebx, ecx
pop ecx eax
xor edx, edx
; inc edi ; file_sector_offset_low
push eax
xor eax, eax
add edi, 1 ; you cannot use INC EDI for qword!!!
adc [ebp+exFAT.RDI_high], eax
pop eax
; inc eax ; RFile_start_sector_low
push ebx
xor ebx, ebx
add eax, 1 ; you cannot use INC EAX for qword!!!
adc [ebp+exFAT.RAX_high], ebx
pop ebx
test ecx, ecx
jz .done
.alignedSector:
; DEBUGF 1, "K : exFAT_ReadFile.alignedSector \n"
; shl edi, 9 ; RFile_start_sector_low * 512
push ebx
mov ebx, [ebp+exFAT.RDI_high]
shld ebx, edi, 5 ; *32
shl edi, 5 ; *32
shld ebx, edi, 4 ; *16
shl edi, 4 ; *16
mov [ebp+exFAT.RDI_high], ebx
pop ebx
push ebx
xor ebx, ebx
mov [ebp+exFAT.RCX_high], ebx
add ecx, edi ; requested size + file_offset_low
mov ebx, [ebp+exFAT.RDI_high]
adc [ebp+exFAT.RCX_high], ebx
pop ebx
xor edi, edi
mov [ebp+exFAT.RDI_high], edi
mov edi, [ebp+exFAT.SECTORS_PER_CLUSTER]
shl edi, 9 ; bytes per cluster
.alignedCluster:
; DEBUGF 1, "K : exFAT_ReadFile.alignedCluster RAX_H:%x EAX:%x RDX_H:%x EDX:%x EDI:%x\n", [ebp+exFAT.RAX_high], eax, [ebp+exFAT.RDX_high], edx, edi
cmp ecx, 512
jc .sectorPiece
mov edx, [ebp+exFAT.RAX_high]
mov [ebp+exFAT.RDX_high], edx
mov edx, eax ; edx << RFile_start_sector_low
xor eax, eax
mov [ebp+exFAT.RAX_high], eax
mov eax, esi ; eax << cluster
@@:
push eax
xor eax, eax
sub ecx, edi ; requested size low - bytes per cluster
sbb [ebp+exFAT.RCX_high], eax
pop eax
jbe .readEnd
; push edi
; lea edi, [ebp+exFAT.file_dir_entry]
; 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 [edi+1], 11b
; pop edi
test byte [ebp+exFAT.General_Sec_Flags], 11b
jz .get_FAT
inc eax ; inc cluster
jmp .continue
.get_FAT:
; DEBUGF 1, "K : exFAT_ReadFile.get_FAT \n"
call exFAT_get_FAT
jc .noaccess4
cmp eax, 2
jb .fileEnd2
.continue:
; DEBUGF 1, "K : exFAT_ReadFile.continue \n"
cmp eax, [ebp+exFAT.fatRESERVED]
jae .fileEnd2
inc esi ; inc cluster
cmp eax, esi
jz @b
.fragmentEnd:
; DEBUGF 1, "K : exFAT_ReadFile.fragmentEnd \n"
xchg eax, esi
dec eax
dec eax
push ebx edx
xor edx, edx
imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER] ; Sector edx:eax
xor ebx, ebx
add eax, [ebp+exFAT.CLUSTER_HEAP_START]
adc edx, ebx
mov [ebp+exFAT.RAX_high], edx
pop edx ebx
push dword [ebp+exFAT.RCX_high]
push ecx ; requested size low
mov ecx, [ebp+exFAT.RAX_high]
mov [ebp+exFAT.RCX_high], ecx
mov ecx, eax ; ecx << RFile_start_sector_low
xor eax, eax
mov [ebp+exFAT.RAX_high], eax
mov eax, esi ; eax << custer
dec eax
dec eax
push ebx edx
xor edx, edx
imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER] ; Sector edx:eax
xor ebx, ebx
add eax, [ebp+exFAT.CLUSTER_HEAP_START]
adc edx, ebx
mov [ebp+exFAT.RAX_high], edx
pop edx ebx
push dword [ebp+exFAT.RAX_high]
push eax
.readFragment:
; DEBUGF 1, "K : exFAT_ReadFile.readFragment \n"
push eax
mov eax, [ebp+exFAT.RDX_high]
sub ecx, edx ; RFile_start_sector_low - RFile_start_sector_low
sbb [ebp+exFAT.RCX_high], eax
pop eax
mov eax, edx
; xor edx, edx
mov edx, [ebp+exFAT.RDX_high]
; DEBUGF 1, "K : exFAT fs_read64_app EDX:%x EAX:%x ECX:%x EBX:%x EBP:%x\n", edx, eax, ecx, ebx, ebp
call fs_read64_app
; DEBUGF 1, "K : exFAT fs_read64_app Output EAX:%x ECX:%x EBX:%x\n", eax, ecx, ebx
; shl ecx, 9
push ebx
mov ebx, [ebp+exFAT.RCX_high]
shld ebx, ecx, 5 ; *32
shl ecx, 5 ; *32
shld ebx, ecx, 4 ; *16
shl ecx, 4 ; *16
mov [ebp+exFAT.RCX_high], ebx
pop ebx
add ebx, ecx
test eax, eax
pop eax
pop dword [ebp+exFAT.RAX_high]
jnz .noaccess3
pop ecx
pop dword [ebp+exFAT.RCX_high]
xor edx, edx
mov [ebp+exFAT.RDX_high], edx
jecxz .done_1
jmp .alignedCluster
.done_1:
jmp .done
.readEnd:
; DEBUGF 1, "K : exFAT_ReadFile.readEnd \n"
push ebx
add ecx, edi ; requested size + bytes per cluster
mov ebx, [ebp+exFAT.RDI_high]
adc [ebp+exFAT.RCX_high], ebx
pop ebx
mov edi, [ebp+exFAT.RCX_high]
mov [ebp+exFAT.RDI_high], edi
mov edi, ecx
and ecx, 511
and dword [ebp+exFAT.RCX_high], 0
; shr edi, 9
push ebx
mov ebx, [ebp+exFAT.RDI_high]
shrd edi, ebx, 5 ; /32
shr ebx, 5 ; /32
shrd edi, ebx, 4 ; /16
shr ebx, 4 ; /16
mov [ebp+exFAT.RDI_high], ebx
pop ebx
dec eax
dec eax
push ebx edx
xor edx, edx
imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER] ; Sector edx:eax
xor ebx, ebx
add eax, [ebp+exFAT.CLUSTER_HEAP_START]
adc edx, ebx
mov [ebp+exFAT.RAX_high], edx
pop edx ebx
add eax, edi ; RFile_start_sector_low - file_sector_offset_low
push ebx
mov ebx, [ebp+exFAT.RDI_high]
adc [ebp+exFAT.RAX_high], ebx
pop ebx
push dword [ebp+exFAT.RCX_high]
push ecx
push dword [ebp+exFAT.RAX_high]
push eax
mov ecx, [ebp+exFAT.RAX_high]
mov [ebp+exFAT.RCX_high], ecx
mov ecx, eax
jmp .readFragment
.noaccess3:
; DEBUGF 1, "K : exFAT_ReadFile.noaccess3 \n"
pop eax
pop dword [ebp+exFAT.RAX_high]
.noaccess2:
; DEBUGF 1, "K : exFAT_ReadFile.noaccess2 \n"
mov byte [esp], ERROR_DEVICE
.done:
; DEBUGF 1, "K : exFAT_ReadFile.done \n"
call exFAT_unlock
pop eax edx
sub ebx, edx
; DEBUGF 1, "K : exFAT_ReadFile Return EBX:%x\n", ebx
; push eax
; pushfd
; pop eax
; DEBUGF 1, "K : eFlags:%x\n",eax
; pop eax
; DEBUGF 1, "K : EAX:%x EBX:%x ECX:%x EDX:%x\n", eax, ebx, ecx, edx
; DEBUGF 1, "K : EBP:%x ESI:%x EDI:%x\n", ebp, esi, edi
ret
.fileEnd:
; DEBUGF 1, "K : exFAT_ReadFile.fileEnd \n"
mov byte [esp], ERROR_END_OF_FILE
jmp .done
.noaccess4:
; DEBUGF 1, "K : exFAT_ReadFile.noaccess4 \n"
mov byte [esp], ERROR_DEVICE
jmp @f
.fileEnd2:
; DEBUGF 1, "K : exFAT_ReadFile.fileEnd2 \n"
mov byte [esp], ERROR_END_OF_FILE
@@:
inc esi
xor ecx, ecx
mov [ebp+exFAT.RCX_high], ecx
jmp .fragmentEnd
;------------------------------------------------------------------------------
exFAT_ReadFolder:
; DEBUGF 1, "K : exFAT_ReadFolder \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
; push eax
; pushfd
; pop eax
; DEBUGF 1, "K : eFlags:%x\n",eax
; pop eax
; DEBUGF 1, "K : EAX:%x EBX:%x ECX:%x EDX:%x\n", eax, ebx, ecx, edx
; DEBUGF 1, "K : EBP:%x ESI:%x EDI:%x\n", ebp, esi, edi
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> exFAT structure
; esi -> path string in UTF-8
; out:
; eax, ebx = return values for sysfunc 70
call exFAT_lock
xor eax, eax
mov [ebp+exFAT.General_Sec_Flags], eax
mov eax, [ebp+exFAT.ROOT_CLUSTER]
; DEBUGF 1, "K : exFAT.ROOT_CLUSTER: %x\n", eax
cmp byte [esi], 0
jz .doit
; push ebp
; mov ebp,[esp+12+8+4+4]
; DEBUGF 1, "K : exFAT Input FS EBP:%x\n", ebp
; pop ebp
call exFAT_hd_find_lfn
; push ebp
; mov ebp,[esp+12+8+4+4]
; DEBUGF 1, "K : exFAT Output FS EBP:%x\n", ebp
; pop ebp
jc .error
; jmp .error
; test byte [edi+11], 0x10 ; do not allow read files
; jz .accessDenied
lea eax, [ebp+exFAT.file_dir_entry]
test byte [eax+4], 10000b ; do not allow read files
jz .accessDenied
; mov eax, [edi+20-2]
; mov ax, [edi+26] ; eax=cluster
lea eax, [ebp+exFAT.str_ext_dir_entry]
push eax
movzx eax, byte [eax+1]
mov [ebp+exFAT.General_Sec_Flags], eax
mov eax, [esp]
mov eax, [eax+8] ; LOW dword of Valid data length - WARNING!!! late rewrite
mov [ebp+exFAT.valid_data_length], eax
pop eax
mov eax, [eax+20] ; cluster
jmp .doit_1
.doit:
mov dword [ebp+exFAT.valid_data_length], 0xffffffff ; for ROOT
.doit_1:
; DEBUGF 1, "K : exFAT.valid_data_length %x\n", [ebp+exFAT.valid_data_length]
; DEBUGF 1, "K : exFAT_ReadFolder.doit \n"
sub esp, 262*2 ; reserve space for LFN
push dword [ebx+8] ; cp866/UNICODE name
mov edx, [ebx+16] ; pointer to buffer
; init header
push eax
mov edi, edx
mov ecx, 32/4
xor eax, eax
rep stosd
pop eax
mov byte [edx], 1 ; version
; mov esi, edi ; esi points to BDFE
mov [ebp+exFAT.points_to_BDFE], edi
; DEBUGF 1, "K : exFAT.points_to_BDFE start EDI: %x\n", edi
mov ecx, [ebx+12] ; number of blocks to read
mov ebx, [ebx+4] ; index of the first block
;------------------------------------------------------------------------------
; DEBUGF 1, "K : exFAT_ReadFolder 1 ECX: %x\n", ecx
cmp [ebp+exFAT.valid_data_length], 0xffffffff
je .num_read_blocks
inc dword [edx+8] ; new file found
test ecx, ecx
jz .num_read_blocks
test ebx, ebx
jnz .dec_offset
; DEBUGF 1, "K : exFAT_ReadFolder create .. dir \n"
inc dword [edx+4] ; new file block copied
push eax esi
mov esi, edi ; [ebp+exFAT.points_to_BDFE]
mov [esi], dword 0x10 ; attributes
xor eax, eax
mov [esi+8], eax ; creation time
mov [esi+12], dword 0x010101 ; eax ; creation date
mov [esi+16], eax ; last access time
mov [esi+20], dword 0x020202 ;eax ; last access date
mov [esi+24], eax ; last write time
mov [esi+28], dword 0x010303 ; eax ; last write date
mov [esi+32], eax ; file size (low dword)
mov [esi+36], eax ; file size (high dword)
push ebp
lea ebp, [esp+4+12]
; DEBUGF 1, "K : exFAT_ReadFolder 1 ESI: %x EBP: %x\n", esi, ebp
; DEBUGF 1, "K : exFAT_ReadFolder old file [EBP-4]: %x [EBP]: %x [EBP+4]: %x [EBP+8]: %x\n", [ebp-4], [ebp], [ebp+4], [ebp+8]
mov eax, [ebp-4]
mov [esi+4], eax ; cp866/UNICODE name
mov [ebp], dword 0x002e002e ; imitate dir '..'
xor eax, eax
mov [ebp+4], eax
call exFAT_entry_to_bdfe2.copy_path
pop ebp
mov [ebp+exFAT.points_to_BDFE], esi
; DEBUGF 1, "K : exFAT_ReadFolder 2 ESI: %x EBP: %x\n", esi, ebp
pop esi eax
dec ecx
jmp .num_read_blocks
.dec_offset:
dec ebx
.num_read_blocks:
; DEBUGF 1, "K : exFAT_ReadFolder 2 ECX: %x\n", ecx
;------------------------------------------------------------------------------
lea esi, [esp+4] ; buffer for UTF-16 name (space for LFN)
mov [ebp+exFAT.LFN_reserve_place], esi
; push eax
; dec eax
; dec eax
; imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER]
; add eax, [ebp+exFAT.CLUSTER_HEAP_START]
; DEBUGF 1, "K : exFAT ROOT SECTOR: %x\n", eax
; pop eax
mov [ebp+exFAT.secondary_dir_entry], dword 1
.new_cluster:
; DEBUGF 1, "K : exFAT_ReadFolder.new_cluster \n"
mov [ebp+exFAT.cluster_tmp], eax
test eax, eax
; jz .notfound
jnz @f
jmp .notfound
@@:
dec eax
dec eax
imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER]
push [ebp+exFAT.SECTORS_PER_CLUSTER]
add eax, [ebp+exFAT.CLUSTER_HEAP_START]
push ebx
.new_sector:
; DEBUGF 1, "K : exFAT_ReadFolder.new_sector \n"
lea ebx, [ebp+exFAT.buffer]
mov edi, ebx
push eax
; DEBUGF 1, "K : exFAT fs_read32_sys N1 EAX: %x\n", eax
call fs_read32_sys
test eax, eax
pop eax
jnz .notfound2
add ebx, 512
push eax
.l1:
; DEBUGF 1, "K : exFAT_ReadFolder.l1 \n"
; push esi
; lea esi, [esp+20]
call exFAT_get_name
; pop esi
jc .l2
; cmp byte [edi], 0xC1 ; File Name Extension Directory Entry of ExFAT
; jnz .do_bdfe
xor eax, eax
cmp [ebp+exFAT.secondary_dir_entry], eax
jz .do_bdfe
; add edi, 0x20
; DEBUGF 1, "K : exFAT_ReadFolder.do_bdfe EDI: %x EBX: %x\n", edi, ebx
; DEBUGF 1, "K : exFAT_ReadFolder.do_bdfe EDI:%x [EDI]:%x NAME:%s\n", edi, [edi], edi
cmp edi, ebx
jb .do_bdfe
pop eax
inc eax
dec dword [esp+4]
jnz @f
mov eax, [ebp+exFAT.cluster_tmp]
test eax, eax
jz .done
; 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], 11b
jz .get_FAT_1
inc eax
jmp .continue_1
.get_FAT_1:
; DEBUGF 1, "K : exFAT_ReadFolder N1 exFAT_get_FAT Input EAX: %x\n", eax
call exFAT_get_FAT
; DEBUGF 1, "K : exFAT_ReadFolder N1 exFAT_get_FAT Output EAX: %x\n", eax
jc .notfound2
cmp eax, 2
jb .done
.continue_1:
cmp eax, [ebp+exFAT.fatRESERVED]
jae .done
push eax
mov eax, [ebp+exFAT.SECTORS_PER_CLUSTER]
mov [esp+8], eax
pop eax
mov [ebp+exFAT.cluster_tmp], eax
dec eax
dec eax
imul eax, [ebp+exFAT.SECTORS_PER_CLUSTER]
add eax, [ebp+exFAT.DATA_START]
@@:
; DEBUGF 1, "K : exFAT_ReadFolder.@@ \n"
lea ebx, [ebp+exFAT.buffer]
mov edi, ebx
push eax
; DEBUGF 1, "K : exFAT fs_read32_sys N2 EAX: %x\n", eax
call fs_read32_sys
test eax, eax
pop eax
jnz .notfound2
add ebx, 512
push eax
.do_bdfe:
; DEBUGF 1, "K : exFAT_ReadFolder.do_bdfe \n"
inc dword [edx+8] ; new file found
dec dword [esp+4]
jns .l2
; DEBUGF 1, "K : exFAT_ReadFolder.do_bdfe ECX: %x\n", ecx
dec ecx
js .l2
inc dword [edx+4] ; new file block copied
push esi edi
mov esi, [ebp+exFAT.points_to_BDFE]
lea edi, [ebp+exFAT.file_dir_entry]
push ebp
lea ebp, [esp+20+4+4]
; DEBUGF 1, "K : exFAT_ReadFolder ESI: %x EBP: %x\n", esi, ebp
; DEBUGF 1, "K : exFAT_ReadFolder.do_bdfe EDI:%x [EDI]:%x ESI:%x [ESI]:%x EBP:%x NAME:%s\n", edi, [edi], esi, [esi], ebp, ebp
call exFAT_entry_to_bdfe
pop ebp
mov [ebp+exFAT.points_to_BDFE], esi
pop edi esi
.l2:
; DEBUGF 1, "K : exFAT_ReadFolder.l2 \n"
add edi, 0x20
; DEBUGF 1, "K : exFAT_ReadFolder.do_bdfe EDI: %x EBX: %x\n", edi, ebx
cmp edi, ebx
jb .l1
pop eax
inc eax
dec dword [esp+4]
jnz .new_sector
mov eax, [ebp+exFAT.cluster_tmp]
test eax, eax
jz .done
push eax
mov eax, [ebp+exFAT.SECTORS_PER_CLUSTER]
shl eax, 9
sub [ebp+exFAT.valid_data_length], eax
pop eax
jbe .done
; 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], 11b
jz .get_FAT
inc eax
jmp .continue
.get_FAT:
; DEBUGF 1, "K : exFAT_ReadFolder N2 exFAT_get_FAT Input EAX: %x\n", eax
call exFAT_get_FAT
; DEBUGF 1, "K : exFAT_ReadFolder N2 exFAT_get_FAT Output EAX: %x\n", eax
jc .notfound2
cmp eax, 2
jb .done
.continue:
cmp eax, [ebp+exFAT.fatRESERVED]
jae .done
push eax
mov eax, [ebp+exFAT.SECTORS_PER_CLUSTER]
mov [esp+8], eax
pop eax
pop ebx
add esp, 4
jmp .new_cluster
;------------------------------------------------------------------------------
.notfound2:
; DEBUGF 1, "K : exFAT_ReadFolder.notfound2 \n"
add esp, 8
.notfound:
; DEBUGF 1, "K : exFAT_ReadFolder.notfound \n"
add esp, 262*2+4
; DEBUGF 1, "K : exFAT_ReadFolder.ERROR_DEVICE \n"
push ERROR_DEVICE
jmp @f
;------------------------------------------------------------------------------
.done:
; DEBUGF 1, "K : exFAT_ReadFolder.done \n"
; DEBUGF 1, "K : exFAT_ReadFolder TotalBloks: %x\n", [edx+8]
; DEBUGF 1, "K : exFAT_ReadFolder Read Bloks: %x\n", [edx+4]
add esp, 262*2+12
pushd 0
; DEBUGF 1, "K : exFAT_ReadFolder.done ECX: %x\n", ecx
dec ecx
js @f
; DEBUGF 1, "K : exFAT_ReadFolder.ERROR_END_OF_FILE \n"
mov byte [esp], ERROR_END_OF_FILE
@@:
mov ebx, [edx+4]
;------------------------------------------------------------------------------
.ret:
; DEBUGF 1, "K : exFAT_ReadFolder.ret \n"
; DEBUGF 1, "K : exFAT_ReadFile Return ESI:%x\n", esi
call exFAT_unlock
pop eax
; DEBUGF 1, "K : exFAT_ReadFile Return EBX:%x\n", ebx
; mov esi, [ebp+exFAT.LFN_reserve_place]
; push eax
; pushfd
; pop eax
; DEBUGF 1, "K : eFlags:%x\n",eax
; pop eax
; DEBUGF 1, "K : EAX:%x EBX:%x ECX:%x EDX:%x\n", eax, ebx, ecx, edx
; DEBUGF 1, "K : EBP:%x ESI:%x EDI:%x\n", ebp, esi, edi
ret
;------------------------------------------------------------------------------
.error:
; DEBUGF 1, "K : exFAT_ReadFolder.error \n"
push eax
xor ebx, ebx
jmp .ret
;------------------------------------------------------------------------------
.accessDenied:
; DEBUGF 1, "K : exFAT_ReadFolder.ERROR_ACCESS_DENIED \n"
push ERROR_ACCESS_DENIED
xor ebx, ebx
jmp .ret
;------------------------------------------------------------------------------
exFAT_GetFileInfo:
; DEBUGF 1, "K : exFAT_GetFileInfo \n"
cmp byte [esi], 0
jz .volume
call exFAT_lock
call exFAT_hd_find_lfn
jc @f
lea edi, [ebp+exFAT.file_dir_entry]
push ebp
xor ebp, ebp
mov esi, [ebx+16]
mov dword [esi+4], ebp
call exFAT_entry_to_bdfe2
pop ebp
xor eax, eax
@@:
push eax
call exFAT_unlock
pop eax
@@:
ret
.volume:
; DEBUGF 1, "K : exFAT_GetFileInfo.volume \n"
mov eax, dword[ebp+exFAT.Length]
mov edx, dword[ebp+exFAT.Length+4]
mov edi, [ebx+16]
shld edx, eax, 9
shl eax, 9
mov [edi+36], edx
mov [edi+32], eax
mov eax, [ebx+8]
mov byte [edi], 8
mov [edi+4], eax
test eax, eax
jz @b
lea esi, [ebp+exFAT.volumeLabel]
mov ecx, 11
@@:
mov byte [esi+ecx], 0
dec ecx
jz @f
cmp byte [esi+ecx], ' '
jz @b
@@:
mov cl, 12
add edi, 40
cmp eax, 2
jz @f
rep movsb
xor eax, eax
ret
@@:
lodsb
stosw
loop @b
ret
;------------------------------------------------------------------------------
exFAT_notroot_next:
; DEBUGF 1, "K : exFAT_notroot_next \n"
push ecx
lea ecx, [ebp+exFAT.buffer+0x200-0x20]
cmp edi, ecx
jae exFAT_notroot_next_sector
add edi, 0x20
@@:
pop ecx
ret
;exFAT_notroot_next_write:
; push ecx
; lea ecx, [ebp+exFAT.buffer+0x200]
; cmp edi, ecx
; jc @b
; push eax
; call exFAT_notroot_end_write
; pop eax
exFAT_notroot_next_sector:
push [ebp+exFAT.longname_sec2]
pop [ebp+exFAT.longname_sec1]
push eax
; DEBUGF 1, "K : exFAT_notroot_next.exFAT_get_sector In EAX:%x\n", eax
call exFAT_get_sector
; DEBUGF 1, "K : exFAT_notroot_next.exFAT_get_sector Out EAX:%x\n", eax
mov [ebp+exFAT.longname_sec2], eax
pop eax
mov ecx, [eax+4]
inc ecx
cmp ecx, [ebp+exFAT.SECTORS_PER_CLUSTER]
jae exFAT_notroot_next_cluster
mov [eax+4], ecx
jmp @f
exFAT_notroot_next_err:
; dec ecx
pop ecx
; js .1
movi eax, ERROR_FILE_NOT_FOUND
;.1:
stc
ret
exFAT_notroot_next_cluster:
push eax
mov eax, [eax]
push edi
lea edi, [ebp+exFAT.str_ext_dir_entry]
; 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 [edi+1], 11b
pop edi
jz .get_FAT
inc eax
jmp .continue
.get_FAT:
call exFAT_get_FAT
.continue:
mov ecx, eax
pop eax
jc exFAT_notroot_first.deverr
cmp ecx, 2
jb exFAT_notroot_next_err
cmp ecx, [ebp+exFAT.fatRESERVED]
jae exFAT_notroot_next_err
mov [eax], ecx
and dword [eax+4], 0
@@:
pop ecx
exFAT_notroot_first:
; DEBUGF 1, "K : exFAT_notroot_first \n"
; DEBUGF 1, "K : exFAT_notroot_first.exFAT_get_sector In EAX:%x\n", eax
call exFAT_get_sector
; DEBUGF 1, "K : exFAT_notroot_first.exFAT_get_sector Out EAX:%x\n", eax
push ebx
lea edi, [ebp+exFAT.buffer]
mov ebx, edi
call fs_read32_sys
pop ebx
test eax, eax
jz .ret ; CF=0
push ecx
.deverr:
pop ecx
mov eax, ERROR_DEVICE
stc
.ret:
ret
;fat_notroot_begin_write:
; push eax edi
; call fat_notroot_first
; pop edi eax
; ret
;fat_notroot_end_write:
; call fat_get_sector
; push ebx
; lea ebx, [ebp+FAT.buffer]
; call fs_write32_sys
; pop ebx
; ret
;--------------------------------------
exFAT_get_sector:
push ecx
mov ecx, [eax]
; DEBUGF 1, "K : exFAT_get_sector In [EAX]:%x [EAX+4]:%x\n", ecx, [eax+4]
dec ecx
dec ecx
imul ecx, [ebp+exFAT.SECTORS_PER_CLUSTER]
; add ecx, [ebp+exFAT.DATA_START]
add ecx, [ebp+exFAT.CLUSTER_HEAP_START]
add ecx, [eax+4]
mov eax, ecx
pop ecx
ret
;------------------------------------------------------------------------------