0,0 → 1,1805 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2021-2022. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License. ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
$Revision: 7136 $ |
|
; 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 entry’s 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 |
;------------------------------------------------------------------------------ |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |