From f8da95f800dd049c95e6a2563725f8448a9ff0f0 Mon Sep 17 00:00:00 2001 From: Marat Zakiyanov Date: Thu, 3 Mar 2022 22:00:47 +0000 Subject: [PATCH] exFAT file system support (only read) git-svn-id: svn://kolibrios.org@9734 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/blkdev/disk.inc | 4 + kernel/trunk/blkdev/disk_cache.inc | 2 +- kernel/trunk/fs/exfat.inc | 1805 ++++++++++++++++++++++++++++ kernel/trunk/fs/fs_lfn.inc | 1 + 4 files changed, 1811 insertions(+), 1 deletion(-) create mode 100644 kernel/trunk/fs/exfat.inc diff --git a/kernel/trunk/blkdev/disk.inc b/kernel/trunk/blkdev/disk.inc index ee5506fa4a..5755a68291 100644 --- a/kernel/trunk/blkdev/disk.inc +++ b/kernel/trunk/blkdev/disk.inc @@ -1252,6 +1252,9 @@ end virtual call fat_create_partition test eax, eax jnz .success + call exFAT_create_partition + test eax, eax + jnz .success call ntfs_create_partition test eax, eax jnz .success @@ -1338,6 +1341,7 @@ endp ; but instead pop return address and return directly to the caller ; otherwise simply return dyndisk_handler: +; DEBUGF 1, "K : FS Input Path:%s\n",esi push ebx edi ; save registers used in file_system_lfn ; 1. Acquire the mutex. mov ecx, disk_list_mutex diff --git a/kernel/trunk/blkdev/disk_cache.inc b/kernel/trunk/blkdev/disk_cache.inc index a6cfd309dd..470c0fe8fa 100644 --- a/kernel/trunk/blkdev/disk_cache.inc +++ b/kernel/trunk/blkdev/disk_cache.inc @@ -57,7 +57,7 @@ fs_read64_sys: ; Read several sequential sectors using cache #2. ; in: edx:eax = start sector, relative to start of partition ; in: ecx = number of sectors to read -; in: edi -> buffer +; in: ebx -> buffer ; in: ebp -> PARTITION ; out: eax = error code, 0 = ok ; out: ecx = number of sectors that were read diff --git a/kernel/trunk/fs/exfat.inc b/kernel/trunk/fs/exfat.inc new file mode 100644 index 0000000000..c244aa4d1c --- /dev/null +++ b/kernel/trunk/fs/exfat.inc @@ -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 +;------------------------------------------------------------------------------ \ No newline at end of file diff --git a/kernel/trunk/fs/fs_lfn.inc b/kernel/trunk/fs/fs_lfn.inc index a4a22ac597..08c4a0957f 100644 --- a/kernel/trunk/fs/fs_lfn.inc +++ b/kernel/trunk/fs/fs_lfn.inc @@ -788,6 +788,7 @@ include "parse_fn.inc" include "fs_common.inc" include "iso9660.inc" ; read for CD filesystem include "fat.inc" +include "exfat.inc" include "ntfs.inc" include "ext.inc" include "xfs.asm"