diff --git a/kernel/trunk/fs/ext.inc b/kernel/trunk/fs/ext.inc new file mode 100644 index 0000000000..a230df9220 --- /dev/null +++ b/kernel/trunk/fs/ext.inc @@ -0,0 +1,2508 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2013-2016. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License. ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; EXT external functions +; in: +; ebx -> parameter structure of sysfunc 70 +; ebp -> EXTFS structure +; [esi]+[[esp+4]] = name +; out: +; eax, ebx = return values for sysfunc 70 +iglobal +align 4 +ext_user_functions: + dd ext_free + dd (ext_user_functions_end - ext_user_functions - 4) / 4 + dd ext_ReadFile + dd ext_ReadFolder + dd ext_CreateFile + dd ext_WriteFile + dd ext_SetFileEnd + dd ext_GetFileInfo + dd ext_SetFileInfo + dd 0 + dd ext_Delete + dd ext_CreateFolder +ext_user_functions_end: +endg + +struct DIRENTRY +inodeNumber dd ? +entryLength dw ? +nameLength db ? +fileType db ? +name db ? ; rb [nameLength] +ends + +struct INODE +accessMode dw ? +UID dw ? +fileSize dd ? +accessedTime dd ? +inodeModified dd ? +dataModified dd ? +deletedTime dd ? +GID dw ? +linksCount dw ? +sectorsUsed dd ? +featureFlags dd ? +reserved dd ? +blockNumbers rd 12 +addressBlock dd ? +doubleAddress dd ? +tripleAddress dd ? +generation dd ? +ACL dd ? +fileSizeHigh dd ? +ends + +struct BGDESCR ; block group descriptor +blockBitmap dd ? +inodeBitmap dd ? +inodeTable dd ? +blocksFree dw ? +inodesFree dw ? +directoriesCount dw ? +reserved rb 14 +ends + +struct SUPERBLOCK +inodesTotal dd ? +blocksTotal dd ? +blocksReserved dd ? +blocksFree dd ? +inodesFree dd ? +firstGroupBlock dd ? +sectorsPerBlockLog dd ? ; shift for 1024 +fragmentSizeLog dd ? +blocksPerGroup dd ? +fragmentsPerGroup dd ? +inodesPerGroup dd ? +lastMountTime dd ? +lastWriteTime dd ? +mountCount dw ? +mountMax dw ? +magic dw ? +state dw ? +errorHandling dw ? +additionalVersion dw ? +lastCheck dd ? +checkInterval dd ? +creatorOS dd ? +dynamicVersionFlag dd ? +reservedUID dw ? +reservedGID dw ? +firstInode dd ? +inodeSize dw ? +thisBlockGroup dw ? +compatibleFlags dd ? +incompatibleFlags dd ? +RO_compatibleFlags dd ? +ends + +; ext4 extent tree +struct NODEHEADER ; tree node header +magic dw ? ; 0xF30A +entriesFolow dw ? +entriesMax dw ? +currentDepth dw ? +generation dd ? +ends + +struct INDEX ; root/branch +fileBlock dd ? +nodeBlock dd ? +nodeBlockHigh dw ? +reserved dw ? +ends + +struct EXTENT ; leaf +fileBlock dd ? +blocksCount dw ? +fsBlockHigh dw ? +fsBlock dd ? +ends + +ROOT_INODE = 2 +PERMISSIONS = 110110110b +EXTENTS_USED = 80000h +TYPE_MASK = 0F000h +FLAG_FILE = 8000h +DIRECTORY = 4000h +DIR_FLAG_FILE = 1 +DIR_DIRECTORY = 2 +KOS_HIDDEN = 2 +KOS_DIRECTORY = 10h +READ_ONLY = 1 + +; Implemented "incompatible" features: +; 2 = have file type in directory entry +; 40h = extents +; 200h = flexible block groups +INCOMPATIBLE_SUPPORT = 242h +; Read only support for "incompatible" features: +INCOMPATIBLE_READ_SUPPORT = 240h + +; Implemented "read-only" features: +; 1 = sparse superblock +; 2 = 64-bit file size +READ_ONLY_SUPPORT = 3 + +struct EXTFS PARTITION +Lock MUTEX +mountType dd ? +sectorsPerBlockLog dd ? ; shift for 512 +bytesPerBlock dd ? +sectorsPerBlock dd ? +dwordsPerBlock dd ? +dwordsPerBranch dd ? ; dwordsPerBlock ^ 2 +mainBlockBuffer dd ? +tempBlockBuffer dd ? +align 512 +superblock SUPERBLOCK +align 1024 +rootInodeBuffer INODE +align 1024 +mainInodeBuffer INODE +align 1024 +tempInodeBuffer INODE +ends + +; mount if it's a valid EXT partition +ext2_create_partition: +; in: +; ebp -> PARTITION structure +; ebx -> boot sector +; ebx+512 -> buffer +; out: +; eax -> EXTFS structure, 0 = not EXT + push ebx + cmp dword [esi+DISK.MediaInfo.SectorSize], 512 + jnz .fail + mov eax, 2 + add ebx, 512 + call fs_read32_sys + test eax, eax + jnz .fail + cmp [ebx+SUPERBLOCK.magic], 0xEF53 + jne .fail + cmp [ebx+SUPERBLOCK.state], 1 + jne .fail + test [ebx+SUPERBLOCK.incompatibleFlags], not INCOMPATIBLE_SUPPORT + jnz .fail + cmp [ebx+SUPERBLOCK.sectorsPerBlockLog], 6 ; 64KB + ja .fail + cmp [ebx+SUPERBLOCK.inodeSize], 1024 + ja .fail + cmp [ebx+SUPERBLOCK.blocksPerGroup], 0 + je .fail + cmp [ebx+SUPERBLOCK.inodesPerGroup], 0 + je .fail + stdcall kernel_alloc, 1000h + test eax, eax + jz .fail + mov ecx, dword [ebp+PARTITION.FirstSector] + mov dword [eax+EXTFS.FirstSector], ecx + mov ecx, dword [ebp+PARTITION.FirstSector+4] + mov dword [eax+EXTFS.FirstSector+4], ecx + mov ecx, dword [ebp+PARTITION.Length] + mov dword [eax+EXTFS.Length], ecx + mov ecx, dword [ebp+PARTITION.Length+4] + mov dword [eax+EXTFS.Length+4], ecx + mov ecx, [ebp+PARTITION.Disk] + mov [eax+EXTFS.Disk], ecx + mov [eax+EXTFS.FSUserFunctions], ext_user_functions + + push ebp esi edi + mov ebp, eax + lea ecx, [eax+EXTFS.Lock] + call mutex_init + mov esi, ebx + lea edi, [ebp+EXTFS.superblock] + mov ecx, 512/4 + rep movsd ; copy superblock + mov ecx, [ebx+SUPERBLOCK.sectorsPerBlockLog] + inc ecx + mov [ebp+EXTFS.sectorsPerBlockLog], ecx + mov eax, 1 + shl eax, cl + mov [ebp+EXTFS.sectorsPerBlock], eax + shl eax, 9 + mov [ebp+EXTFS.bytesPerBlock], eax + shl eax, 1 + push eax + shr eax, 3 + mov [ebp+EXTFS.dwordsPerBlock], eax + mul eax + mov [ebp+EXTFS.dwordsPerBranch], eax + call kernel_alloc + test eax, eax + jz .error + mov [ebp+EXTFS.mainBlockBuffer], eax + add eax, [ebp+EXTFS.bytesPerBlock] + mov [ebp+EXTFS.tempBlockBuffer], eax + mov [ebp+EXTFS.mountType], 0 + test [ebx+SUPERBLOCK.RO_compatibleFlags], not READ_ONLY_SUPPORT + jnz .read_only + test [ebx+SUPERBLOCK.incompatibleFlags], INCOMPATIBLE_READ_SUPPORT + jz @f +.read_only: + or [ebp+EXTFS.mountType], READ_ONLY +@@: ; read root inode + lea ebx, [ebp+EXTFS.rootInodeBuffer] + mov eax, ROOT_INODE + call readInode + test eax, eax + jnz @f + mov eax, ebp + pop edi esi ebp ebx + ret + +@@: + stdcall kernel_free, [ebp+EXTFS.mainBlockBuffer] +.error: + stdcall kernel_free, ebp + pop edi esi ebp +.fail: + pop ebx + xor eax, eax + ret + +; unmount EXT partition +ext_free: +; in: eax -> EXTFS structure + push eax + stdcall kernel_free, [eax+EXTFS.mainBlockBuffer] + call kernel_free + ret + +extfsWriteBlock: + push fs_write64_sys + jmp @f +; in: +; eax = block number +; ebx -> buffer +extfsReadBlock: + push fs_read64_sys +@@: + push ecx edx + mov ecx, [ebp+EXTFS.sectorsPerBlock] + mul ecx + call dword[esp+8] + pop edx ecx + add esp, 4 + test eax, eax + jz @f + movi eax, ERROR_DEVICE + stc +@@: + ret + +extfsReadDescriptor: +; in: eax = block group number +; out: +; [ebp+EXTFS.tempBlockBuffer] -> relevant block +; eax -> block group descriptor, 0 = error + push edx ebx + shl eax, 5 + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + add eax, [ebp+EXTFS.superblock.firstGroupBlock] + inc eax + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .fail + mov eax, ebx + add eax, edx +@@: + pop ebx edx + ret + +.fail: + xor eax, eax + stc + jmp @b + +extfsWriteDescriptor: +; in: +; eax = block group number +; [ebp+EXTFS.tempBlockBuffer] -> relevant block + push edx ebx + shl eax, 5 + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + add eax, [ebp+EXTFS.superblock.firstGroupBlock] + inc eax + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsWriteBlock + pop ebx edx + ret + +extfsResourceFree: +; in: +; ecx=0 -> block, ecx=1 -> inode +; eax = block/inode number + push ebx edx + sub eax, [ebp+EXTFS.superblock.firstGroupBlock] + xor edx, edx + div [ebp+EXTFS.superblock.blocksPerGroup] + push eax edx + call extfsReadDescriptor + jc .fail + inc [eax+BGDESCR.blocksFree+ecx*2] + mov eax, [eax+BGDESCR.blockBitmap+ecx*4] + mov ebx, [ebp+EXTFS.mainBlockBuffer] + mov edx, eax + call extfsReadBlock + jc .fail + pop eax + push edx + mov edx, eax + and edx, 31 + shr eax, 5 + shl eax, 2 + add eax, [ebp+EXTFS.mainBlockBuffer] + btr [eax], edx + pop eax + mov ebx, [ebp+EXTFS.mainBlockBuffer] + call extfsWriteBlock + jc @f + inc [ebp+EXTFS.superblock.blocksFree+ecx*4] + pop eax + call extfsWriteDescriptor +.ret: + pop edx ebx + ret + +.fail: + pop eax +@@: + pop eax + movi eax, ERROR_DEVICE + jmp .ret + +freeDoublyIndirectBlock: +; in: eax = doubly-indirect block number +; out: eax=1 -> finished + test eax, eax + jz .complete + push eax + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + pop eax + jc .ret + xor ecx, ecx + call extfsResourceFree + mov edx, ebx + add edx, [ebp+EXTFS.bytesPerBlock] +@@: + mov eax, [ebx] + test eax, eax + jz .complete + call extfsResourceFree + add ebx, 4 + cmp ebx, edx + jb @b +.ret: + xor eax, eax + ret + +.complete: + inc eax + ret + +inodeBlockAlloc: +; in: esi -> inode +; out: ebx = block number +; TODO: fix to have correct preference. + mov eax, ROOT_INODE + call extfsBlockAlloc + jc @f + mov eax, [ebp+EXTFS.sectorsPerBlock] + add [esi+INODE.sectorsUsed], eax + xor eax, eax +@@: + ret + +extfsBlockAlloc: ; also erases +; in: eax = inode number +; out: ebx = block number + xor ebx, ebx + call extfsResourceAlloc + jc @f + push ebx ecx edi + mov ecx, [ebp+EXTFS.dwordsPerBlock] + mov edi, [ebp+EXTFS.tempBlockBuffer] + mov ebx, edi + xor eax, eax + rep stosd + pop edi ecx + mov eax, [esp] + call extfsWriteBlock + pop ebx +@@: + ret + +extfsResourceAlloc: +; in: +; eax = inode number +; ebx=0 -> block, ebx=1 -> inode +; out: +; ebx = block/inode number + push ecx edx esi edi + dec eax + xor edx, edx + div [ebp+EXTFS.superblock.inodesPerGroup] + push eax eax + mov esi, .forward ; search forward, then backward +.test_block_group: + call extfsReadDescriptor + jc .fail + dec [eax+BGDESCR.blocksFree+ebx*2] + mov eax, [eax+BGDESCR.blockBitmap+ebx*4] + push ebx + mov ebx, [ebp+EXTFS.mainBlockBuffer] + mov edx, eax + mov edi, ebx + call extfsReadBlock + pop ebx + jc .fail + mov ecx, [ebp+EXTFS.superblock.blocksPerGroup+ebx*8] + or eax, -1 + shr ecx, 5 + jz .next + repz scasd + jz .next + sub edi, 4 + mov eax, [edi] + not eax + bsf eax, eax + bts [edi], eax + sub edi, [ebp+EXTFS.mainBlockBuffer] + shl edi, 3 + add eax, edi + mov ecx, eax + mov eax, edx + push ebx + mov ebx, [ebp+EXTFS.mainBlockBuffer] + call extfsWriteBlock + pop ebx + jc .fail + mov eax, [esp] + mul [ebp+EXTFS.superblock.blocksPerGroup+ebx*8] + add eax, ecx + dec [ebp+EXTFS.superblock.blocksFree+ebx*4] + mov ebx, eax + pop eax + add esp, 4 + call extfsWriteDescriptor +@@: + pop edi esi edx ecx + ret + +.fail: + pop eax eax + movi eax, ERROR_DEVICE + jmp @b + +.next: + jmp esi + +.forward: + inc dword[esp] + mov eax, [esp] + mul [ebp+EXTFS.superblock.blocksPerGroup+ebx*8] + neg ebx + cmp eax, [ebp+EXTFS.superblock.blocksTotal+ebx*4] + ja @f + neg ebx + mov eax, [esp] + jmp .test_block_group + +@@: + neg ebx + mov eax, [esp+4] + mov [esp], eax + mov esi, .backward +.backward: + sub dword[esp], 1 + jc .fail + mov eax, [esp] + jmp .test_block_group + +extfsGetFileBlock: +; in: +; ecx = file block number +; esi -> inode +; out: +; ecx = block number + test [esi+INODE.featureFlags], EXTENTS_USED + jz .listTreeSearch + pushad + add esi, INODE.blockNumbers +.extentTreeSearch: + cmp word [esi+NODEHEADER.magic], 0xF30A + jne .fail + movzx ebx, [esi+NODEHEADER.entriesFolow] + add esi, sizeof.NODEHEADER + cmp word [esi-sizeof.NODEHEADER+NODEHEADER.currentDepth], 0 + je .leaf_block + test ebx, ebx + jz .fail ; empty +@@: + cmp ebx, 1 + je .end_search_index + cmp ecx, [esi+INDEX.fileBlock] + jb .fail + cmp ecx, [esi+sizeof.INDEX+INDEX.fileBlock] + jb .end_search_index + add esi, sizeof.INDEX + dec ebx + jmp @b + +.end_search_index: + mov ebx, [ebp+EXTFS.tempBlockBuffer] + mov eax, [esi+INDEX.nodeBlock] + call extfsReadBlock + jc .fail + mov esi, ebx + jmp .extentTreeSearch + +.leaf_block: + test ebx, ebx + jz .fail + mov edx, [esi+EXTENT.fileBlock] + cmp ecx, edx + jb .fail + movzx edi, [esi+EXTENT.blocksCount] + add edx, edi + cmp ecx, edx + jb .end_search_extent + add esi, sizeof.EXTENT + dec ebx + jmp .leaf_block + +.end_search_extent: + sub ecx, [esi+EXTENT.fileBlock] + add ecx, [esi+EXTENT.fsBlock] + mov PUSHAD_ECX, ecx + popad + xor eax, eax + ret + +.fail: + popad + movi eax, ERROR_FS_FAIL + stc + ret + +.get_indirect_block: + push edx ebx + mov eax, [esi+INODE.addressBlock] + test eax, eax + jz .fail3 + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc @f + mov ecx, [ebx+ecx*4] +@@: + pop ebx edx + ret + +.get_direct_block: + mov ecx, [esi+INODE.blockNumbers+ecx*4] + xor eax, eax + ret + +.listTreeSearch: + cmp ecx, 12 + jb .get_direct_block + sub ecx, 12 + cmp ecx, [ebp+EXTFS.dwordsPerBlock] + jb .get_indirect_block + sub ecx, [ebp+EXTFS.dwordsPerBlock] + cmp ecx, [ebp+EXTFS.dwordsPerBranch] + jb .get_double_indirect_block +; triply-indirect blocks + sub ecx, [ebp+EXTFS.dwordsPerBranch] + push edx ebx + mov eax, [esi+INODE.tripleAddress] + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .fail2 + xor edx, edx + mov eax, ecx + div [ebp+EXTFS.dwordsPerBranch] +; eax = number in triply-indirect block, edx = number in branch + mov eax, [ebx+eax*4] + test eax, eax + jz .fail3 + call extfsReadBlock + jc .fail2 + mov eax, edx + jmp @f + +.fail3: + pop ebx edx + movi eax, ERROR_FS_FAIL + stc + ret + +.get_double_indirect_block: + push edx ebx + mov eax, [esi+INODE.doubleAddress] + test eax, eax + jz .fail3 + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .fail2 + mov eax, ecx +@@: + xor edx, edx + div [ebp+EXTFS.dwordsPerBlock] +; eax = number in doubly-indirect block, edx = number in indirect block + mov eax, [ebx+eax*4] + test eax, eax + jz .fail3 + call extfsReadBlock + jc .fail2 + mov ecx, [ebx+edx*4] +.fail2: + pop ebx edx + ret + +extfsSetFileBlock: +; in: +; ecx = file block number +; edi = block number +; esi -> inode + push ebx ecx edx + cmp ecx, 12 + jb .direct_block + sub ecx, 12 + cmp ecx, [ebp+EXTFS.dwordsPerBlock] + jb .indirect_block + sub ecx, [ebp+EXTFS.dwordsPerBlock] + cmp ecx, [ebp+EXTFS.dwordsPerBranch] + jb .double_indirect_block +; triple indirect blocks + sub ecx, [ebp+EXTFS.dwordsPerBranch] + mov eax, [esi+INODE.tripleAddress] + test eax, eax + jnz @f + call inodeBlockAlloc + jc .ret + mov [esi+INODE.tripleAddress], ebx + mov eax, ebx +@@: + push eax + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .fail_alloc_4 + xor edx, edx + mov eax, ecx + div [ebp+EXTFS.dwordsPerBranch] +; eax = number in triply-indirect block, edx = number in branch + lea ecx, [ebx+eax*4] + mov eax, [ebx+eax*4] + test eax, eax + jnz @f + call inodeBlockAlloc + jc .fail_alloc_4 + mov [ecx], ebx + mov eax, [esp] + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsWriteBlock + jc .fail_alloc_4 + mov eax, [ecx] +@@: + mov [esp], eax + call extfsReadBlock + jc .fail_alloc_4 + mov eax, edx + jmp @f + +.double_indirect_block: + mov eax, [esi+INODE.doubleAddress] + test eax, eax + jnz .double_indirect_present + call inodeBlockAlloc + jc .ret + mov [esi+INODE.doubleAddress], ebx + mov eax, ebx +.double_indirect_present: + push eax + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .fail_alloc_4 + mov eax, ecx +@@: + xor edx, edx + div [ebp+EXTFS.dwordsPerBlock] +; eax = number in doubly-indirect block, edx = number in indirect block + lea ecx, [ebx+edx*4] + push ecx + lea ecx, [ebx+eax*4] + cmp dword[ecx], 0 + jne @f + call inodeBlockAlloc + jc .fail_alloc_8 + mov [ecx], ebx + mov eax, [esp+4] + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsWriteBlock + jc .fail_alloc_8 +@@: + mov eax, [ecx] + push eax + call extfsReadBlock + jc .fail_alloc_12 + pop eax ecx edx + mov [ecx], edi + call extfsWriteBlock + jmp .ret + +.indirect_block: + mov eax, [esi+INODE.addressBlock] + test eax, eax + jnz @f + call inodeBlockAlloc + jc .ret + mov [esi+INODE.addressBlock], ebx + mov eax, ebx +@@: + push eax + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .fail_alloc_4 + mov [ebx+ecx*4], edi + pop eax + call extfsWriteBlock + jmp .ret + +.direct_block: + mov [esi+INODE.blockNumbers+ecx*4], edi + xor eax, eax +.ret: + pop edx ecx ebx + ret + +.fail_alloc_12: + pop ebx +.fail_alloc_8: + pop ebx +.fail_alloc_4: + pop ebx + jmp .ret + +extfsEraseFileBlock: ; also allocates +; in: +; edx = inode number +; eax = file block number +; [ebp+EXTFS.tempInodeBuffer] = inode + push ebx ecx edx edi esi + mov edi, eax + mov ecx, eax + lea esi, [ebp+EXTFS.tempInodeBuffer] + call extfsGetFileBlock + jc @f + test ecx, ecx + jz .allocate + mov edx, ecx + mov ecx, [ebp+EXTFS.bytesPerBlock] + mov edi, [ebp+EXTFS.tempBlockBuffer] + xor eax, eax + rep stosb + mov eax, edx + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsWriteBlock + jmp @f + +.allocate: + mov eax, edx + call extfsBlockAlloc + jc @f + mov ecx, edi + mov edi, ebx + lea esi, [ebp+EXTFS.tempInodeBuffer] + call extfsSetFileBlock + jc @f + mov eax, [ebp+EXTFS.sectorsPerBlock] + add [esi+INODE.sectorsUsed], eax + xor eax, eax +@@: + pop esi edi edx ecx ebx + ret + +extfsFreeFileBlock: +; in: +; eax = file block number +; [ebp+EXTFS.tempInodeBuffer] = inode + push ebx ecx edi esi + mov edi, eax + mov ecx, eax + lea esi, [ebp+EXTFS.tempInodeBuffer] + call extfsGetFileBlock + jc @f + test ecx, ecx + jz @f + mov eax, ecx + xor ecx, ecx + call extfsResourceFree + mov ecx, edi + xor edi, edi + lea esi, [ebp+EXTFS.tempInodeBuffer] + call extfsSetFileBlock + mov eax, [ebp+EXTFS.sectorsPerBlock] + sub [esi+INODE.sectorsUsed], eax + xor eax, eax +@@: + pop esi edi ecx ebx + ret + +extfsReadFileBlock: +; in: +; eax = file block number +; [ebp+EXTFS.tempInodeBuffer] = inode +; out: +; [ebp+EXTFS.mainBlockBuffer] -> block + push ebx ecx edx esi + mov ecx, eax + lea esi, [ebp+EXTFS.tempInodeBuffer] + call extfsGetFileBlock + jc .ret + test ecx, ecx + jz @f + mov eax, ecx + mov ebx, [ebp+EXTFS.mainBlockBuffer] + call extfsReadBlock +.ret: + pop esi edx ecx ebx + ret + +@@: + movi eax, ERROR_FS_FAIL + stc + jmp .ret + +extfsWriteFileBlock: +; in: +; eax = file block number +; [ebp+EXTFS.tempInodeBuffer] = inode +; [ebp+EXTFS.mainBlockBuffer] -> block to write + push ebx ecx edx esi + mov ecx, eax + lea esi, [ebp+EXTFS.tempInodeBuffer] + call extfsGetFileBlock + jc @f + test ecx, ecx + jz @b + mov eax, ecx + mov ebx, [ebp+EXTFS.mainBlockBuffer] + call extfsWriteBlock +@@: + pop esi edx ecx ebx + ret + +getInodeLocation: +; in: eax = inode number +; out: +; ebx = inode sector +; edx = offset in sector + dec eax + xor edx, edx + div [ebp+EXTFS.superblock.inodesPerGroup] + mov ecx, edx + shl eax, 5 + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + add eax, [ebp+EXTFS.superblock.firstGroupBlock] + inc eax + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc @f + add ebx, edx + mov ebx, [ebx+BGDESCR.inodeTable] + mov eax, ecx + mov ecx, [ebp+EXTFS.sectorsPerBlockLog] + shl ebx, cl + mul [ebp+EXTFS.superblock.inodeSize] + mov edx, eax + shr eax, 9 + and edx, 511 + add ebx, eax + xor eax, eax +@@: + ret + +writeInode: +; in: +; eax = inode number +; ebx -> inode data + push edx edi esi ecx ebx eax + mov edi, ebx + call fsGetTime + add eax, 978307200 + mov [edi+INODE.inodeModified], eax + pop eax + call getInodeLocation + jc .ret + mov eax, ebx + mov ebx, [ebp+EXTFS.tempBlockBuffer] + mov ecx, eax + call fs_read32_sys + test eax, eax + jnz @f + mov eax, ecx + mov esi, edi + movzx ecx, [ebp+EXTFS.superblock.inodeSize] + mov edi, edx + add edi, ebx + rep movsb + call fs_write32_sys +.ret: + pop ebx ecx esi edi edx + ret + +@@: + movi eax, ERROR_DEVICE + stc + jmp .ret + +readInode: +; in: +; eax = inode number +; ebx -> inode buffer + push edx edi esi ecx ebx + mov edi, ebx + call getInodeLocation + jc @f + mov eax, ebx + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call fs_read32_sys + test eax, eax + jnz @b + movzx ecx, [ebp+EXTFS.superblock.inodeSize] + mov esi, edx + add esi, ebx + rep movsb + xor eax, eax +@@: + pop ebx ecx esi edi edx + ret + +extfsExtendFile: +; in: +; eax = inode number +; ecx = new size + push ebx ecx edx esi edi eax + lea ebx, [ebp+EXTFS.tempInodeBuffer] + call readInode + jc .ret + cmp [ebx+INODE.fileSize], ecx + jnc .ret + mov eax, [ebx+INODE.fileSize] + push eax + sub ecx, eax + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + test edx, edx + jz .start_aligned + mov esi, [ebp+EXTFS.bytesPerBlock] + sub esi, edx + cmp esi, ecx + jbe @f + mov esi, ecx +@@: ; clear esi trailing bytes in block number eax + push eax + call extfsReadFileBlock + pop edi + jc .error_inode_size + push edi ecx + xor eax, eax + mov ecx, esi + mov edi, ebx + add edi, edx + rep stosb + pop ecx eax + call extfsWriteFileBlock + jc .error_inode_size + add [esp], esi + sub ecx, esi + jz .write_inode +.start_aligned: + cmp ecx, [ebp+EXTFS.bytesPerBlock] + jb @f + mov eax, [esp] + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + mov edx, [esp+4] + call extfsEraseFileBlock + jc .error_inode_size + mov eax, [ebp+EXTFS.bytesPerBlock] + sub ecx, eax + add [esp], eax + jmp .start_aligned + +@@: ; handle the remaining bytes + test ecx, ecx + jz .write_inode + mov eax, [esp] + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + mov edx, [esp+4] + call extfsEraseFileBlock + jc .error_inode_size + add [esp], ecx +.write_inode: + xor eax, eax +.error_inode_size: + lea ebx, [ebp+EXTFS.tempInodeBuffer] + pop [ebx+INODE.fileSize] + push eax + mov eax, [esp+4] + call writeInode + pop ebx + jc .ret + xchg eax, ebx + cmp ebx, eax ; set CF +.ret: + pop edi edi esi edx ecx ebx + ret + +extfsTruncateFile: +; in: +; eax = inode number +; ecx = new size + push ebx ecx edx esi edi eax + lea ebx, [ebp+EXTFS.tempInodeBuffer] + call readInode + jc .ret + cmp ecx, [ebx+INODE.fileSize] + jnc .ret + mov eax, [ebx+INODE.fileSize] + push eax + sub ecx, eax + not ecx + inc ecx + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + test edx, edx + jz .start_aligned + mov esi, edx + cmp esi, ecx + jbe @f +; if the size to truncate is smaller than the unaligned bytes +; we're going to clear neccessary bytes from the EOF + push eax + call extfsReadFileBlock + pop edi + jc .error_inode_size + push edi ecx + mov edi, [ebp+EXTFS.mainBlockBuffer] + sub edx, ecx + add edi, edx + xor eax, eax + rep stosb + pop ecx eax + call extfsWriteFileBlock + jc .error_inode_size + sub [esp], ecx + jmp .write_inode + +@@: + call extfsFreeFileBlock + sub [esp], esi + sub ecx, esi + jz .write_inode +.start_aligned: + cmp ecx, [ebp+EXTFS.bytesPerBlock] + jb @f + mov eax, [esp] + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + dec eax + call extfsFreeFileBlock + mov eax, [ebp+EXTFS.bytesPerBlock] + sub ecx, eax + sub [esp], eax + jmp .start_aligned + +@@: ; handle the remaining bytes + test ecx, ecx + jz .write_inode + mov eax, [esp] + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + dec eax + push eax + call extfsReadFileBlock + pop edi + jc .error_inode_size + push edi ecx + mov edi, [ebp+EXTFS.mainBlockBuffer] + mov edx, [ebp+EXTFS.bytesPerBlock] + sub edx, ecx + add edi, edx + xor eax, eax + rep stosb + pop ecx eax + call extfsWriteFileBlock + jc .error_inode_size + sub [esp], ecx +.write_inode: + xor eax, eax +.error_inode_size: + lea ebx, [ebp+EXTFS.tempInodeBuffer] + pop [ebx+INODE.fileSize] + push eax + mov eax, [esp+4] + call writeInode + pop ebx + jc .ret + xchg eax, ebx + cmp ebx, eax ; set CF +.ret: + pop edi edi esi edx ecx ebx + ret + +linkInode: +; in: +; eax = inode on which to link +; ebx = inode to link +; esi -> name +; dl = file type + push esi edi ebx ecx eax edx + call strlen + add ecx, 8 ; directory entry size + push esi ebx ecx + xor ecx, ecx + lea esi, [ebp+EXTFS.tempInodeBuffer] + mov ebx, esi + call readInode + jc .error_inode_read + mov ecx, [ebp+EXTFS.sectorsPerBlockLog] + mov eax, [esi+INODE.sectorsUsed] + shr eax, cl + xor ecx, ecx + push eax ; maximum file block number + push ecx ; current file block number +.searchBlock: + call extfsGetFileBlock + jc .error_get_inode_block + test ecx, ecx + jz .alloc_block + push ecx + mov eax, ecx + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .error_block_read + mov ecx, [esp+8] + mov edi, [ebp+EXTFS.tempBlockBuffer] + mov edx, edi + add edx, [ebp+EXTFS.bytesPerBlock] +.searchSpace: + movzx eax, [edi+DIRENTRY.entryLength] + test eax, eax + jz .zeroLength + cmp [edi+DIRENTRY.inodeNumber], 0 + je .unusedEntry + movzx ebx, [edi+DIRENTRY.nameLength] + add ebx, 8+3 + and ebx, -4 + sub eax, ebx + add edi, ebx + cmp eax, ecx + jb .nextEntry + sub edi, ebx + mov [edi+DIRENTRY.entryLength], bx + add edi, ebx + mov [edi+DIRENTRY.entryLength], ax + jmp .found + +.unusedEntry: + cmp eax, ecx + jge .found +.nextEntry: + add edi, eax + cmp edi, edx + jb .searchSpace + jmp .nextBlock + +.zeroLength: + mov [edi+DIRENTRY.entryLength], cx + mov eax, edx + sub eax, edi + cmp eax, ecx + jge .found + mov [edi+DIRENTRY.inodeNumber], 0 + mov [edi+DIRENTRY.entryLength], ax +; this block wasn't linking to the next one, so write it, and use the next block + pop eax + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsWriteBlock + jc .error_get_inode_block + inc dword[esp] + mov ecx, [esp] + call extfsGetFileBlock + jc .error_get_inode_block + test ecx, ecx + jz .alloc_block + push ecx + jmp .prepare_block + +.nextBlock: + add esp, 4 + inc dword[esp] + mov ecx, [esp] + cmp ecx, [esp+4] + jbe .searchBlock +.alloc_block: + mov eax, [esp+12] + call extfsBlockAlloc + jc .error_get_inode_block + mov ecx, [esp] + mov edi, ebx + call extfsSetFileBlock + jc .error_get_inode_block + mov eax, [ebp+EXTFS.bytesPerBlock] + add [esi+INODE.fileSize], eax + mov eax, [ebp+EXTFS.sectorsPerBlock] + add [esi+INODE.sectorsUsed], eax + mov eax, [esp+24] + mov ebx, esi + call writeInode + jc .error_get_inode_block + push edi ; save the block we just allocated +.prepare_block: + mov eax, [esp] + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .error_block_read + mov edi, ebx + mov eax, [ebp+EXTFS.bytesPerBlock] + mov [edi+DIRENTRY.entryLength], ax +.found: + pop edx ecx ecx ecx ebx esi + push ebx + mov [edi], ebx ; save inode + mov eax, [esp+4] + cmp [ebp+EXTFS.superblock.dynamicVersionFlag], 0 + je .name + mov [edi+DIRENTRY.fileType], al +.name: + sub ecx, 8 + mov [edi+DIRENTRY.nameLength], cl + add edi, 8 + rep movsb + mov eax, edx + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsWriteBlock + jc .error_block_write + mov eax, [esp] + lea ebx, [ebp+EXTFS.tempInodeBuffer] + call readInode + jc .error_block_write + pop eax + inc [ebx+INODE.linksCount] + call writeInode + jc @f + xor eax, eax +@@: + pop edx ecx ecx ebx edi esi + ret + +.error_block_read: + pop ebx +.error_get_inode_block: + pop ebx ebx +.error_inode_read: + pop ebx ebx +.error_block_write: + pop ebx + jmp @b + +unlinkInode: +; in: +; eax = inode from which to unlink +; ebx = inode to unlink +; out: +; eax = current number of links to inode, -1 = error + push edx esi edi ebx + lea ebx, [ebp+EXTFS.tempInodeBuffer] + call readInode + jc .fail + push eax + lea esi, [ebp+EXTFS.tempInodeBuffer] +.loop: + mov ecx, [esp] + call extfsGetFileBlock + jc .fail_loop + test ecx, ecx + jz .fail_loop + mov eax, ecx + mov edi, ecx + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .fail_loop +.first_dir_entry: ; edi -> block + mov eax, [esp+4] + cmp [ebx+DIRENTRY.inodeNumber], eax + jne @f + mov [ebx+DIRENTRY.inodeNumber], 0 + mov word [ebx+DIRENTRY.nameLength], 0 ; fileType = 0 + jmp .write_block + +@@: + mov edx, ebx + add edx, [ebp+EXTFS.bytesPerBlock] + push edx + mov edx, ebx + movzx ecx, [ebx+DIRENTRY.entryLength] + add ebx, ecx +.dir_entry: + cmp [ebx+DIRENTRY.inodeNumber], eax + jne @f + mov cx, [ebx+DIRENTRY.entryLength] + add [edx+DIRENTRY.entryLength], cx + pop eax + jmp .write_block + +@@: + mov edx, ebx + movzx ecx, [ebx+DIRENTRY.entryLength] + test ecx, ecx + jz .fail_inode + add ebx, ecx + cmp ebx, [esp] + jb .dir_entry + pop ecx + inc dword[esp] + jmp .loop + +.fail_inode: + pop eax +.fail_loop: + pop eax +.fail: + or eax, -1 + jmp @f + +.write_block: + pop eax + mov eax, edi + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsWriteBlock + jc .fail + mov eax, [esp] + lea ebx, [ebp+EXTFS.tempInodeBuffer] + call readInode + jc .fail + dec word [ebx+INODE.linksCount] + mov eax, [esp] + call writeInode + jc .fail + movzx eax, word [ebx+INODE.linksCount] +@@: + pop ebx edi esi edx + ret + +findInode_parent: +; in: esi -> path +; out: +; edi -> file name +; esi = inode + push esi + xor edi, edi +.loop: + cmp byte [esi], '/' + jne @f + mov edi, esi + inc esi + jmp .loop + +@@: + inc esi + cmp byte [esi-1], 0 + jne .loop + cmp edi, 0 + jne @f +; parent is root + pop edi + dec esi + jmp .get_inode + +@@: ; parent is folder + mov byte [edi], 0 + inc edi + pop esi +.get_inode: + push ebx edx + stdcall findInode, 0 + pop edx ebx + ret + +findInode: +; in: [esi]+[[esp+4]] = name +; out: +; [ebp+EXTFS.mainInodeBuffer] = inode +; esi = inode number +; dl = first byte of file/folder name + lea edx, [ebp+EXTFS.rootInodeBuffer] + cmp [edx+INODE.sectorsUsed], 0 + je .not_found + cmp byte [esi], 0 + jne .next_path_part +; root + push edi ecx + lea esi, [ebp+EXTFS.rootInodeBuffer] + lea edi, [ebp+EXTFS.mainInodeBuffer] + movzx ecx, [ebp+EXTFS.superblock.inodeSize] + rep movsb + pop ecx edi + xor eax, eax + xor dl, dl + mov esi, ROOT_INODE + ret 4 + +.next_path_part: + push [edx+INODE.sectorsUsed] + xor ecx, ecx +.folder_block_cycle: + push ecx + xchg esi, edx + call extfsGetFileBlock + jc .error_get_block + xchg esi, edx + mov eax, ecx + mov ebx, [ebp+EXTFS.mainBlockBuffer] + call extfsReadBlock + jc .error_get_block + push esi edx + sub esp, 256 + mov edx, ebx + add edx, [ebp+EXTFS.bytesPerBlock] +.start_rec: + cmp [ebx+DIRENTRY.inodeNumber], 0 + jz .next_rec + mov edi, esp + push esi + movzx ecx, [ebx+DIRENTRY.nameLength] + lea esi, [ebx+DIRENTRY.name] + call utf8_to_cp866 + mov ecx, edi + lea edi, [esp+4] + sub ecx, edi ; number of bytes in resulting string + mov esi, [esp] +@@: ; edi -> converted string in stack, ecx = size, esi -> original file path + jecxz .test_find + dec ecx + lodsb + call char_toupper + mov ah, [edi] + inc edi + xchg al, ah + call char_toupper + cmp al, ah + je @b +@@: ; doesn't match + pop esi +.next_rec: + movzx eax, [ebx+DIRENTRY.entryLength] + add ebx, eax + cmp ebx, edx + jb .start_rec + push eax + jmp @f + +.test_find: + cmp byte [esi], 0 + je @f + cmp byte [esi], '/' + jne @b + inc esi +@@: + add esp, 256+4 + pop edx edi ecx +; ebx -> matched directory entry, esi -> name without parent, or not changed + cmp edi, esi + je .next_folder_block + cmp byte [esi], 0 + jnz @f + cmp dword[esp+8], 0 + je .get_inode_ret + mov esi, [esp+8] + mov dword[esp+8], 0 +@@: + mov eax, [ebx+DIRENTRY.inodeNumber] + lea ebx, [ebp+EXTFS.mainInodeBuffer] + call readInode + jc .error_get_inode + movzx eax, [ebx+INODE.accessMode] + and eax, TYPE_MASK + cmp eax, DIRECTORY + jne .not_found ; path folder is a file + pop ecx + mov edx, ebx + jmp .next_path_part + +.next_folder_block: + pop eax + sub eax, [ebp+EXTFS.sectorsPerBlock] + jle .not_found + push eax + inc ecx + jmp .folder_block_cycle + +.get_inode_ret: + pop eax + mov dl, [ebx+DIRENTRY.name] + mov eax, [ebx+DIRENTRY.inodeNumber] + lea ebx, [ebp+EXTFS.mainInodeBuffer] + mov esi, eax + call readInode + ret 4 + +.not_found: + movi eax, ERROR_FILE_NOT_FOUND + stc + ret 4 + +.error_get_block: + pop ebx +.error_get_inode: + pop ebx + ret 4 + +writeSuperblock: + push ebx + mov eax, 2 + lea ebx, [ebp+EXTFS.superblock] + call fs_write32_sys + pop ebx + ret + +extfsWritingInit: + movi eax, ERROR_ACCESS_DENIED + cmp byte [esi], 0 + jz @f + movi eax, ERROR_UNSUPPORTED_FS + test [ebp+EXTFS.mountType], READ_ONLY + jnz @f +ext_lock: + lea ecx, [ebp+EXTFS.Lock] + jmp mutex_lock + +@@: + pop ebx + xor ebx, ebx + ret + +ext_unlock: + lea ecx, [ebp+EXTFS.Lock] + jmp mutex_unlock + +;---------------------------------------------------------------- +ext_ReadFolder: + call ext_lock + cmp byte [esi], 0 + jz .root_folder + push ebx + stdcall findInode, [esp+4+4] + pop ebx + jc .error_ret + lea esi, [ebp+EXTFS.mainInodeBuffer] + test [esi+INODE.accessMode], DIRECTORY + jz .error_not_found + jmp @f + +.root_folder: + lea esi, [ebp+EXTFS.rootInodeBuffer] + lea edi, [ebp+EXTFS.mainInodeBuffer] + movzx ecx, [ebp+EXTFS.superblock.inodeSize] + shr ecx, 2 + push edi + rep movsd + pop esi +@@: + cmp [esi+INODE.fileSize], 0 + je .error_empty_dir + mov edx, [ebx+16] + push edx ; [edi+28] result buffer + push 0 ; [edi+24] end of the current block in folder + pushd [ebx+12] ; [edi+20] files to read + pushd [ebx+4] ; [edi+16] first wanted file + pushd [ebx+8] ; [edi+12] flags + push 0 ; [edi+8] read files + push 0 ; [edi+4] files in folder + push 0 ; [edi] current block index + mov edi, esp ; edi -> local variables + add edx, 32 + xor ecx, ecx + call extfsGetFileBlock + jc .error_get_block + mov eax, ecx + mov ebx, [ebp+EXTFS.mainBlockBuffer] + call extfsReadBlock + jc .error_get_block + mov eax, ebx + add eax, [ebp+EXTFS.bytesPerBlock] + mov [edi+24], eax + mov ecx, [edi+16] +.find_wanted_start: + jecxz .find_wanted_end +.find_wanted_cycle: + cmp [ebx+DIRENTRY.inodeNumber], 0 + jz @f + inc dword [edi+4] + dec ecx +@@: + movzx eax, [ebx+DIRENTRY.entryLength] + cmp eax, 12 ; minimum entry length + jb .error_bad_len + test eax, 3 ; length must be aligned + jnz .error_bad_len + sub [esi+INODE.fileSize], eax + add ebx, eax + cmp ebx, [edi+24] + jb .find_wanted_start + push .find_wanted_start +.end_block: ; read next block + cmp [esi+INODE.fileSize], 0 + jle .end_dir + inc dword [edi] + push ecx + mov ecx, [edi] + call extfsGetFileBlock + jc .error_get_block + mov eax, ecx + mov ebx, [ebp+EXTFS.mainBlockBuffer] + call extfsReadBlock + jc .error_get_block + pop ecx + mov eax, ebx + add eax, [ebp+EXTFS.bytesPerBlock] + mov [edi+24], eax + ret + +.wanted_end: + loop .find_wanted_cycle +.find_wanted_end: + mov ecx, [edi+20] +.wanted_start: + jecxz .wanted_end + cmp [ebx+DIRENTRY.inodeNumber], 0 + jz .empty_rec + inc dword [edi+8] + inc dword [edi+4] + push ebx edi ecx esi edx + mov edi, edx + xor eax, eax + mov ecx, 40 / 4 + rep stosd + mov eax, [ebx+DIRENTRY.inodeNumber] + lea ebx, [ebp+EXTFS.tempInodeBuffer] + call readInode + jc .error_read_subinode + mov esi, ebx + lea edi, [edx+8] + mov eax, [ebx+INODE.inodeModified] + sub eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60 + call fsTime2bdfe + + mov eax, [esi+INODE.accessedTime] + sub eax, 978307200 + call fsTime2bdfe + + mov eax, [esi+INODE.dataModified] + sub eax, 978307200 + call fsTime2bdfe + pop edx + or dword [edx], KOS_DIRECTORY + test [esi+INODE.accessMode], DIRECTORY + jnz @f + xor dword [edx], KOS_DIRECTORY ; mark as file + mov eax, [esi+INODE.fileSize] + stosd + mov eax, [esi+INODE.fileSizeHigh] + stosd +@@: + mov esi, [esp+12] + movzx ecx, [esi+DIRENTRY.nameLength] + lea edi, [edx+40] + lea esi, [esi+DIRENTRY.name] + call utf8_to_cp866 + and byte [edi], 0 + pop esi ecx edi ebx + cmp byte [edx+40], '.' + jne @f + or dword [edx], KOS_HIDDEN +@@: + add edx, 40+264 ; go to the next record + dec ecx +.empty_rec: + movzx eax, [ebx+DIRENTRY.entryLength] + cmp eax, 12 + jb .error_bad_len + test eax, 3 + jnz .error_bad_len + sub [esi+INODE.fileSize], eax + add ebx, eax + cmp ebx, [edi+24] + jb .wanted_start + push .wanted_start + jmp .end_block + +.end_dir: + call ext_unlock + mov edx, [edi+28] + mov ebx, [edi+8] + mov ecx, [edi+4] + mov dword [edx], 1 ; version + mov [edx+4], ebx + mov [edx+8], ecx + lea esp, [edi+32] + mov ecx, 20/4 + lea edi, [edx+12] + xor eax, eax + rep stosd + ret + +.error_bad_len: + movi eax, ERROR_FS_FAIL +.error_read_subinode: +.error_get_block: + lea esp, [edi+32] +.error_ret: + or ebx, -1 + push eax + call ext_unlock + pop eax + ret + +.error_empty_dir: + movi eax, ERROR_FS_FAIL + jmp .error_ret + +.error_not_found: + movi eax, ERROR_FILE_NOT_FOUND + jmp .error_ret + +;---------------------------------------------------------------- +ext_ReadFile: + call ext_lock + push ERROR_ACCESS_DENIED + cmp byte [esi], 0 + jz .error ; root + mov [esp], ebx + stdcall findInode, [esp+4+4] + pop ebx + jc .error_eax + push ERROR_ACCESS_DENIED + lea esi, [ebp+EXTFS.mainInodeBuffer] + mov ax, [esi+INODE.accessMode] + and ax, TYPE_MASK + cmp ax, FLAG_FILE + jnz .error ; not a file + pop eax + mov edi, [ebx+16] + mov ecx, [ebx+12] + mov eax, [ebx+4] + mov edx, [ebx+8] + push ERROR_END_OF_FILE + cmp [esi+INODE.fileSizeHigh], edx + ja @f + jb .error + cmp [esi+INODE.fileSize], eax + jna .error +@@: + add esp, 4 + add eax, ecx + adc edx, 0 + cmp [esi+INODE.fileSizeHigh], edx + ja .read_till_requested + jb .read_whole_file + cmp [esi+INODE.fileSize], eax + jae .read_till_requested +.read_whole_file: + push 1 ; read till the end of file + mov ecx, [esi+INODE.fileSize] + sub ecx, [ebx+4] + jmp @f + +.read_till_requested: + push 0 ; read as much as requested +@@: ; ecx = bytes to read, edi -> buffer + push ecx +; read part of the first block + mov edx, [ebx+8] + mov eax, [ebx+4] + div [ebp+EXTFS.bytesPerBlock] + push eax + push ecx + mov ecx, eax + call extfsGetFileBlock + jc .error_at_first_block + mov ebx, [ebp+EXTFS.mainBlockBuffer] + mov eax, ecx + call extfsReadBlock + jc .error_at_first_block + pop ecx + add ebx, edx + neg edx + add edx, [ebp+EXTFS.bytesPerBlock] + cmp ecx, edx + jbe .only_one_block + mov eax, ecx + sub eax, edx ; bytes to read + mov ecx, edx + push esi + mov esi, ebx + rep movsb + pop esi + mov ebx, edi + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + mov edi, eax +@@: + test edi, edi + jz .finish_block + inc dword [esp] + mov ecx, [esp] + call extfsGetFileBlock + jc .error_at_read_cycle + mov eax, ecx + call extfsReadBlock + jc .error_at_read_cycle + add ebx, [ebp+EXTFS.bytesPerBlock] + dec edi + jmp @b + +.finish_block: ; edx = number of bytes in the last block + test edx, edx + jz .end_read + pop ecx ; block counter + inc ecx + call extfsGetFileBlock + jc .error_at_finish_block + mov edi, ebx + mov eax, ecx + mov ebx, [ebp+EXTFS.mainBlockBuffer] + call extfsReadBlock + jc .error_at_finish_block + push eax + mov ecx, edx +.only_one_block: + mov esi, ebx + rep movsb +.end_read: + call ext_unlock + pop eax ebx eax + test eax, eax + jz @f + movi eax, ERROR_END_OF_FILE +@@: + ret + +.error_at_first_block: + pop ebx +.error_at_read_cycle: + pop ebx +.error_at_finish_block: + pop ebx ebx +.error_eax: + push eax +.error: + call ext_unlock + xor ebx, ebx + pop eax + ret + +;---------------------------------------------------------------- +ext_GetFileInfo: + call ext_lock + mov edx, [ebx+16] + cmp byte [esi], 0 + jz .is_root + push edx + stdcall findInode, [esp+4+4] + mov ebx, edx + pop edx + lea esi, [ebp+EXTFS.mainInodeBuffer] + jnc @f + push eax + call ext_unlock + pop eax + ret + +.is_root: + xor ebx, ebx + lea esi, [ebp+EXTFS.rootInodeBuffer] +@@: + xor eax, eax + mov edi, edx + mov ecx, 40/4 + rep stosd + cmp bl, '.' + jne @f + or dword [edx], KOS_HIDDEN +@@: + or dword [edx], KOS_DIRECTORY + test [esi+INODE.accessMode], DIRECTORY + jnz @f + xor dword [edx], KOS_DIRECTORY ; mark as file + mov eax, [esi+INODE.fileSize] + mov ebx, [esi+INODE.fileSizeHigh] + mov dword [edx+32], eax + mov dword [edx+36], ebx +@@: + lea edi, [edx+8] + mov eax, [esi+INODE.inodeModified] + sub eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60 + call fsTime2bdfe + + mov eax, [esi+INODE.accessedTime] + sub eax, 978307200 + call fsTime2bdfe + + mov eax, [esi+INODE.dataModified] + sub eax, 978307200 + call fsTime2bdfe + call ext_unlock + xor eax, eax + ret + +;---------------------------------------------------------------- +ext_SetFileInfo: + call extfsWritingInit + pushd [ebx+16] + stdcall findInode, [esp+4+4] + pop edx + jc @f + push esi ; inode number + lea esi, [edx+16] + lea edi, [ebp+EXTFS.mainInodeBuffer] + call fsCalculateTime + add eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60 + mov [edi+INODE.accessedTime], eax + + add esi, 8 + call fsCalculateTime + add eax, 978307200 + mov [edi+INODE.dataModified], eax + mov ebx, edi + pop eax + call writeInode +@@: + push eax + jc @f + call writeSuperblock + mov esi, [ebp+PARTITION.Disk] + call disk_sync +@@: + call ext_unlock + pop eax + ret + +;---------------------------------------------------------------- +ext_Delete: + call extfsWritingInit + push esi + stdcall findInode, [esp+4+4] + mov ebx, esi + pop esi + push eax + jc .ret + pop eax + lea edx, [ebp+EXTFS.mainInodeBuffer] + movzx edx, [edx+INODE.accessMode] + and edx, TYPE_MASK + cmp edx, DIRECTORY + jne .file + push esi ebx edx 0 + lea esi, [ebp+EXTFS.mainInodeBuffer] +.checkDirectory: + mov ecx, [esp] + call extfsGetFileBlock + jc .not_empty_eax + test ecx, ecx + jz .empty + mov eax, ecx + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + jc .not_empty_eax + mov edx, ebx + add edx, [ebp+EXTFS.bytesPerBlock] + movzx ecx, [ebx+DIRENTRY.entryLength] + add ebx, ecx +.dir_entry: + cmp byte [ebx+DIRENTRY.nameLength], 1 + jne @f + cmp byte [ebx+DIRENTRY.name], '.' + jne .not_empty +@@: + cmp byte [ebx+DIRENTRY.nameLength], 2 + jne .not_empty + cmp word [ebx+DIRENTRY.name], '..' + jne .not_empty + movzx ecx, [ebx+DIRENTRY.entryLength] + add ebx, ecx + cmp ebx, edx + jb .dir_entry + inc dword[esp] + jmp .checkDirectory + +.empty: + pop edx edx ebx esi +.file: + call findInode_parent + jc .error + mov eax, esi +; save file/folder's and parent's inode + push ebx eax + cmp edx, DIRECTORY + jne @f +; Unlink '.' + mov eax, [esp+4] + call unlinkInode + cmp eax, -1 + je .error_stack8 +; Unlink '..' + mov eax, [esp+4] + mov ebx, [esp] + call unlinkInode + cmp eax, -1 + je .error_stack8 +@@: + pop eax + mov ebx, [esp] + call unlinkInode + cmp eax, -1 + je .error_stack4 + test eax, eax + jz @f +; has hardlinks + xor eax, eax + mov [esp], eax + jmp .disk_sync + +@@: + mov eax, [esp] + lea ebx, [ebp+EXTFS.mainInodeBuffer] + call readInode + jc .error_stack4_eax +; free file's data + lea esi, [ebp+EXTFS.mainInodeBuffer] + xor ecx, ecx +@@: + push ecx + call extfsGetFileBlock + jc .error_stack8_eax + mov eax, ecx + test eax, eax + jz @f + xor ecx, ecx + call extfsResourceFree + pop ecx + inc ecx + jmp @b + +@@: ; free indirect blocks + pop ecx + push edx + lea edi, [ebp+EXTFS.mainInodeBuffer] + mov eax, [edi+INODE.addressBlock] + test eax, eax + jz .success + xor ecx, ecx + call extfsResourceFree + mov eax, [edi+INODE.doubleAddress] + call freeDoublyIndirectBlock + cmp eax, 1 + je .success + mov eax, [edi+INODE.tripleAddress] + test eax, eax + jz .success + push eax + mov ebx, [ebp+EXTFS.tempBlockBuffer] + call extfsReadBlock + pop ecx + jc .error_stack8_eax + mov eax, ecx + xor ecx, ecx + call extfsResourceFree + mov edx, ebx + add edx, [ebp+EXTFS.bytesPerBlock] +@@: + mov eax, [ebx] + test eax, eax + jz .success + push ebx edx + call freeDoublyIndirectBlock + pop edx ebx + cmp eax, 1 + je .success + add ebx, 4 + cmp ebx, edx + jb @b +.success: ; clear the inode, and add deletion time + xor eax, eax + movzx ecx, [ebp+EXTFS.superblock.inodeSize] + rep stosb + lea edi, [ebp+EXTFS.mainInodeBuffer] + call fsGetTime + pop edx + add eax, 978307200 + mov [edi+INODE.deletedTime], eax + mov eax, [esp] + mov ebx, edi + call writeInode + jc .error_stack4_eax + cmp edx, DIRECTORY + jne @f + mov eax, [esp] + dec eax + xor edx, edx + div [ebp+EXTFS.superblock.inodesPerGroup] + push eax + call extfsReadDescriptor + jc .error_stack8 + dec [eax+BGDESCR.directoriesCount] + pop eax + call extfsWriteDescriptor +@@: ; free inode + pop eax + dec eax + xor ecx, ecx + inc ecx + call extfsResourceFree + push eax +.disk_sync: + call writeSuperblock + mov esi, [ebp+PARTITION.Disk] + call disk_sync +.ret: + call ext_unlock + xor ebx, ebx + pop eax + ret + +.not_empty: + pop eax +.error_stack8: + pop eax +.error_stack4: + pop eax + push ERROR_ACCESS_DENIED + jmp .disk_sync + +.not_empty_eax: + pop ebx +.error_stack8_eax: + pop ebx +.error_stack4_eax: + pop ebx +.error: + push eax + jmp .disk_sync + +;---------------------------------------------------------------- +ext_CreateFolder: + call extfsWritingInit + push esi + stdcall findInode, [esp+4+4] + pop esi + jnc .success ; exist + call findInode_parent + jc .error + mov eax, esi + xor ebx, ebx + inc ebx + call extfsResourceAlloc + jc .error + inc ebx + push ebx esi edi + xor al, al + lea edi, [ebp+EXTFS.tempInodeBuffer] + movzx ecx, [ebp+EXTFS.superblock.inodeSize] + rep stosb + lea edi, [ebp+EXTFS.tempInodeBuffer] + call fsGetTime + add eax, 978307200 + mov [edi+INODE.accessedTime], eax + mov [edi+INODE.dataModified], eax + mov ebx, edi + pop edi esi edx +; edx = allocated inode number, edi -> filename, esi = parent inode number + mov [ebx+INODE.accessMode], DIRECTORY or PERMISSIONS + mov eax, edx + call writeInode + jc .error +; link to self + push edx esi + mov eax, edx + mov ebx, eax + mov dl, DIR_DIRECTORY + mov esi, self_link + call linkInode + pop esi edx + jc .error +; link to parent + push edx esi + mov eax, ebx + mov ebx, esi + mov dl, DIR_DIRECTORY + mov esi, parent_link + call linkInode + pop esi edx + jc .error +; link parent to child + mov eax, esi + mov ebx, edx + mov esi, edi + mov dl, DIR_DIRECTORY + call linkInode + jc .error + mov eax, ebx + dec eax + xor edx, edx + div [ebp+EXTFS.superblock.inodesPerGroup] + mov edx, eax + call extfsReadDescriptor + jc @f + inc [eax+BGDESCR.directoriesCount] + mov eax, edx + call extfsWriteDescriptor +.success: +.error: + push eax + call writeSuperblock + mov esi, [ebp+PARTITION.Disk] + call disk_sync + call ext_unlock + pop eax + ret + +@@: + movi eax, ERROR_DEVICE + jmp .error + +self_link db ".", 0 +parent_link db "..", 0 + +;---------------------------------------------------------------- +ext_CreateFile: + call extfsWritingInit + push ebx esi + stdcall findInode, [esp+8+4] + mov esi, [esp] + jc @f + call ext_unlock + stdcall ext_Delete, [esp+8+4] + mov [esp], eax + call ext_lock + pop eax + test eax, eax + jnz .error + mov esi, [esp] +@@: + call findInode_parent + jc .error + mov eax, esi + xor ebx, ebx + inc ebx + call extfsResourceAlloc + jc .error + inc ebx + push ebx esi edi + xor al, al + lea edi, [ebp+EXTFS.tempInodeBuffer] + movzx ecx, [ebp+EXTFS.superblock.inodeSize] + rep stosb + lea edi, [ebp+EXTFS.tempInodeBuffer] + call fsGetTime + add eax, 978307200 + mov [edi+INODE.accessedTime], eax + mov [edi+INODE.dataModified], eax + mov ebx, edi + pop edi esi edx +; edx = allocated inode number, edi -> filename, esi = parent inode number + mov [ebx+INODE.accessMode], FLAG_FILE or PERMISSIONS + mov eax, edx + call writeInode + jc .error +; link parent to child + mov eax, esi + mov ebx, edx + mov esi, edi + mov dl, DIR_FLAG_FILE + call linkInode + jc .error + pop esi ebx + call ext_unlock + jmp ext_WriteFile + +.error: + push eax + call ext_unlock + pop eax ebx ebx + xor ebx, ebx + ret + +;---------------------------------------------------------------- +ext_WriteFile: + call extfsWritingInit + push 0 ebx + stdcall findInode, [esp+8+4] + jc .error + lea edx, [ebp+EXTFS.mainInodeBuffer] + movi eax, ERROR_ACCESS_DENIED + test [edx+INODE.accessMode], FLAG_FILE + jz .error ; not a file + mov ebx, [esp] + push esi ; inode number + mov eax, esi + mov ecx, [ebx+4] + call extfsExtendFile + jc .error2 + mov ecx, [ebx+12] + mov esi, [ebx+16] + mov eax, [edx+INODE.fileSize] + push eax + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + test edx, edx + jz .start_aligned + mov ebx, [ebp+EXTFS.bytesPerBlock] + sub ebx, edx + cmp ebx, ecx + jbe @f + mov ebx, ecx +@@: + push eax + call extfsReadFileBlock + pop edi + jc .error_inode_size + mov eax, edi + push ecx + mov ecx, ebx + mov edi, ebx + add edi, edx + rep movsb + pop ecx + call extfsWriteFileBlock + jc .error_inode_size + add [esp], ebx + sub ecx, ebx + jz .write_inode +.start_aligned: + cmp ecx, [ebp+EXTFS.bytesPerBlock] + jb @f + mov eax, [esp] + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + mov edx, [esp+4] + push eax + call extfsEraseFileBlock + pop edi + jc .error_inode_size + mov eax, edi + push ecx + mov ecx, [ebp+EXTFS.bytesPerBlock] + mov edi, [ebp+EXTFS.mainBlockBuffer] + rep movsb + pop ecx + call extfsWriteFileBlock + jc .error_inode_size + mov eax, [ebp+EXTFS.bytesPerBlock] + sub ecx, eax + add [esp], eax + jmp .start_aligned +@@: ; Handle the remaining bytes. + test ecx, ecx + jz .write_inode + mov eax, [esp] + xor edx, edx + div [ebp+EXTFS.bytesPerBlock] + push eax + call extfsReadFileBlock + pop eax + jnc @f + mov edx, [esp+4] + push eax + call extfsEraseFileBlock + pop edi + jc .error_inode_size + mov eax, edi +@@: + push ecx + mov edi, [ebp+EXTFS.mainBlockBuffer] + rep movsb + pop ecx + call extfsWriteFileBlock + jc .error_inode_size + add [esp], ecx + xor ecx, ecx +.error_inode_size: + mov [esp+12], eax +.write_inode: + lea ebx, [ebp+EXTFS.tempInodeBuffer] + pop [ebx+INODE.fileSize] + pop eax + call writeInode + pop ebx + mov ebx, [ebx+12] + sub ebx, ecx + test eax, eax + jz @f + mov [esp], eax +@@: + call writeSuperblock + mov esi, [ebp+PARTITION.Disk] + call disk_sync +@@: + call ext_unlock + pop eax + ret + +.error2: + pop ebx +.error: + pop ebx ebx + push eax + jmp @b + +;---------------------------------------------------------------- +ext_SetFileEnd: + call extfsWritingInit + pushd [ebx+4] + stdcall findInode, [esp+4+4] + pop ecx + jc @f + lea edx, [ebp+EXTFS.mainInodeBuffer] + movi eax, ERROR_ACCESS_DENIED + cmp [edx+INODE.accessMode], FLAG_FILE + jnz @f ; not a file + mov eax, esi + call extfsExtendFile + jc @f + mov eax, esi + call extfsTruncateFile + jc @f + mov eax, esi + lea ebx, [ebp+EXTFS.tempInodeBuffer] + call writeInode +@@: + push eax + call writeSuperblock + mov esi, [ebp+PARTITION.Disk] + call disk_sync + call ext_unlock + pop eax + ret diff --git a/kernel/trunk/fs/ext2/blocks.inc b/kernel/trunk/fs/ext2/blocks.inc deleted file mode 100644 index bce995391e..0000000000 --- a/kernel/trunk/fs/ext2/blocks.inc +++ /dev/null @@ -1,412 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Contains ext2 block handling code. ;; -;; ;; -;; Copyright (C) KolibriOS team 2013-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;--------------------------------------------------------------------- -; Write ext2 block from memory to disk. -; Input: eax = i_block (block number in ext2 terms); -; ebx = buffer address -; ebp = pointer to EXTFS -; Output: eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_block_write: - push edx ebx ecx - - mov edx, fs_write32_sys - jmp ext2_block_modify - -;--------------------------------------------------------------------- -; Read ext2 block from disk to memory. -; Input: eax = i_block (block number in ext2 terms); -; ebx = address of where to read block -; ebp = pointer to EXTFS -; Output: eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_block_read: - push edx ebx ecx - - mov edx, fs_read32_sys - jmp ext2_block_modify - -;--------------------------------------------------------------------- -; Modify ext2 block. -; Input: eax = i_block (block number in ext2 terms); -; ebx = I/O buffer address; -; edx = fs_read/write32_sys -; ebp = pointer to EXTFS -; edx, ebx, ecx on stack. -; Output: eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_block_modify: - ; Get block number in hard-disk terms in eax. - mov ecx, [ebp + EXTFS.log_block_size] - shl eax, cl - mov ecx, eax - push [ebp + EXTFS.count_block_in_block] - - @@: - mov eax, ecx - call edx - test eax, eax - jnz .fail - - inc ecx - add ebx, 512 - dec dword[esp] - jnz @B - - xor eax, eax - @@: - pop ecx - pop ecx ebx edx - ret - - .fail: - mov eax, ERROR_DEVICE - jmp @B - -;--------------------------------------------------------------------- -; Zeroes a block. -; Input: ebx = block ID. -; ebp = pointer to EXTFS. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_block_zero: - push ebx - - mov eax, ebx - mov ebx, [ebp + EXTFS.ext2_temp_block] - - call ext2_block_read - test eax, eax - jnz .return - - push edi ecx - xor eax, eax - mov ecx, [ebp + EXTFS.block_size] - mov edi, [ebp + EXTFS.ext2_temp_block] - rep stosb - pop ecx edi - - mov eax, [esp] - call ext2_block_write - - .return: - pop ebx - ret - -;--------------------------------------------------------------------- -; Allocates a block. -; Input: eax = inode ID for "preference". -; ebp = pointer to EXTFS. -; Output: Block marked as set in block group. -; eax = error code. -; ebx = block ID. -;--------------------------------------------------------------------- -ext2_block_alloc: - push [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_count] - push EXT2_BLOCK_GROUP_DESC.free_blocks_count - push [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_per_group] - - lea ebx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.free_block_count] - push ebx - - push ext2_bg_read_blk_bitmap - - call ext2_resource_alloc - - ret - -;--------------------------------------------------------------------- -; Zero-allocates a block. -; Input: eax = inode ID for "preference". -; ebp = pointer to EXTFS. -; Output: Block marked as set in block group. -; eax = error code. -; ebx = block ID. -;--------------------------------------------------------------------- -ext2_block_calloc: - call ext2_block_alloc - test eax, eax - jnz @F - - call ext2_block_zero - @@: - ret - -;--------------------------------------------------------------------- -; Frees a block. -; Input: eax = block ID. -; ebp = pointer to EXTFS. -; Output: Block marked as free in block group. -; eax = error code. -;--------------------------------------------------------------------- -ext2_block_free: - push edi ecx - - mov edi, ext2_bg_read_blk_bitmap - xor ecx, ecx - call ext2_resource_free - - pop ecx edi - ret - -;--------------------------------------------------------------------- -; Find parent from file path in block. -; Input: esi = file path. -; ebx = pointer to directory block. -; ebp = pointer to EXTFS structure. -; Output: esi = name without parent, or not changed. -; ebx = directory record matched. -;--------------------------------------------------------------------- -ext2_block_find_parent: - sub esp, 256 ; Space for EXT2 filename. - mov edx, ebx - add edx, [ebp + EXTFS.block_size] ; Save block end. - - .start_rec: - cmp [ebx + EXT2_DIR_STRUC.inode], 0 - jz .next_rec - - mov edi, esp - push esi - movzx ecx, [ebx + EXT2_DIR_STRUC.name_len] - lea esi, [ebx + EXT2_DIR_STRUC.name] - call utf8_to_cp866 - - mov ecx, edi - lea edi, [esp + 4] - sub ecx, edi ; Number of bytes in resulting string. - - mov esi, [esp] - - ; esi: original file path. - ; edi: converted string stored on stack. - ; ecx: size of converted string. - @@: - ; If no bytes left in resulting string, test it. - jecxz .test_find - dec ecx - - lodsb - call char_toupper - - mov ah, [edi] - inc edi - xchg al, ah - call char_toupper - - ; If both are same, check next byte. - cmp al, ah - je @B - @@: ; Doesn't match. - pop esi - - .next_rec: - movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] - add ebx, eax ; Go to next record. - cmp ebx, edx ; Check if this is the end. - jb .start_rec - - add esp, 256 - ret - - .test_find: - cmp byte [esi], 0 - je .ret ; The end reached. - cmp byte [esi], '/' ; If not end of directory name, not matched. - jne @B - inc esi - - .ret: - add esp, 256 + 4 - ret - -;--------------------------------------------------------------------- -; Finds free space in a directory block, modifying last entry appropriately. -; Input: ebp = pointer to EXTFS. -; ecx = size of free space required. -; [EXTFS.ext2_temp_block] contains the block relevant. -; Output: edi = free entry. -; rec_len of free entry is set. -; eax = error code; if the block doesn't link to the next one, this is 0x00000001 on failure. -; ; else, 0xFFFFFFFF. -;--------------------------------------------------------------------- -ext2_block_find_fspace: - push ebx edx - - mov edi, [ebp + EXTFS.ext2_temp_block] - mov edx, edi - add edx, [ebp + EXTFS.block_size] - - @@: - movzx eax, [edi + EXT2_DIR_STRUC.rec_len] - test eax, eax - jz .zero_len - - cmp [edi + EXT2_DIR_STRUC.inode], 0 - je .unused_entry - - ; It's a used entry, so see if we can fit it between current one and next. - ; Subtract the size used by the name and the structure from rec_len. - movzx ebx, [edi + EXT2_DIR_STRUC.name_len] - add ebx, 8 + 3 - and ebx, 0xfffffffc ; Align it on the next 4-byte boundary. - - sub eax, ebx - add edi, ebx - cmp eax, ecx - jb .next_iter - - sub edi, ebx - mov [edi + EXT2_DIR_STRUC.rec_len], bx ; Make previous entry point to us. - add edi, ebx - - mov [edi + EXT2_DIR_STRUC.rec_len], ax ; Make current entry point to next one. - jmp .found - - .unused_entry: - ; It's an unused inode. - cmp eax, ecx - jge .found - - .next_iter: - add edi, eax - cmp edi, edx - jb @B - - .not_found: - xor eax, eax - not eax - jmp .ret - - ; Zero length entry means we have the rest of the block for us. - .zero_len: - mov eax, edx - sub eax, edi - - ; Point to next block. - mov [edi + EXT2_DIR_STRUC.rec_len], ax - - cmp eax, ecx - jge .fits - - mov [edi + EXT2_DIR_STRUC.inode], 0 - - ; It doesn't fit, but the block doesn't link to the next block. - xor eax, eax - inc eax - jmp .ret - - .fits: - mov [edi + EXT2_DIR_STRUC.rec_len], cx - - .found: - xor eax, eax - - .ret: - pop edx ebx - ret - -;--------------------------------------------------------------------- -; Gets the block group's descriptor. -; Input: eax = block group. -; Output: eax = if zero, error; else, points to block group descriptor. -; [EXTFS.ext2_temp_block] contains relevant block. -; ebp = pointer to EXTFS. -;--------------------------------------------------------------------- -ext2_bg_read_desc: - push edx ebx - mov edx, 32 - mul edx ; Get index of descriptor in global_desc_table. - - ; eax: block group descriptor offset relative to global descriptor table start - ; Find the block this block descriptor is in. - div [ebp + EXTFS.block_size] - add eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block] - inc eax - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .fail - - add ebx, edx ; edx: local index of descriptor inside block - mov eax, ebx - - .return: - pop ebx edx - ret - - .fail: - xor eax, eax - jmp .return - -;--------------------------------------------------------------------- -; Writes a block group's descriptor. -; Input: eax = block group. -; [EXTFS.ext2_temp_data] contains the block relevant. -; ebp = pointer to EXTFS. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_bg_write_desc: - push edx ebx - mov edx, 32 - mul edx ; Get index of descriptor in global_desc_table. - - ; eax: block group descriptor offset relative to global descriptor table start - ; Find the block this block descriptor is in. - div [ebp + EXTFS.block_size] - add eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block] - inc eax - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_write - - .return: - pop ebx edx - ret - -;--------------------------------------------------------------------- -; Gets the block group's block bitmap. -; Input: eax = block group. -; Output: eax = if zero, error; else, points to block group descriptor. -; ebx = block bitmap's block (hard disk). -;--------------------------------------------------------------------- -ext2_bg_read_blk_bitmap: - push ecx - - call ext2_bg_read_desc - test eax, eax - jz .fail - - mov ebx, [eax + EXT2_BLOCK_GROUP_DESC.block_bitmap] ; Block number of block group bitmap - in ext2 terms. - - .return: - pop ecx - ret - - .fail: - xor eax, eax - jmp .return - -;--------------------------------------------------------------------- -; Updates superblock, plus backups. -; Input: ebp = pointer to EXTFS. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_sb_update: - push ebx - - mov eax, 2 - lea ebx, [ebp + EXTFS.superblock] - call fs_write32_sys - - pop ebx - ret diff --git a/kernel/trunk/fs/ext2/ext2.asm b/kernel/trunk/fs/ext2/ext2.asm deleted file mode 100644 index 3069f264d1..0000000000 --- a/kernel/trunk/fs/ext2/ext2.asm +++ /dev/null @@ -1,1723 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Contains ext2 initialization, plus syscall handling code. ;; -;; ;; -;; Copyright (C) KolibriOS team 2013-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -include 'ext2.inc' -include 'blocks.inc' -include 'inode.inc' -include 'resource.inc' - -iglobal -align 4 -ext2_user_functions: - dd ext2_free - dd (ext2_user_functions_end - ext2_user_functions - 4) / 4 - dd ext2_Read - dd ext2_ReadFolder - dd ext2_Rewrite - dd ext2_Write - dd ext2_SetFileEnd - dd ext2_GetFileInfo - dd ext2_SetFileInfo - dd 0 - dd ext2_Delete - dd ext2_CreateFolder -ext2_user_functions_end: -endg - -;--------------------------------------------------------------------- -; Locks up an ext2 partition. -; Input: ebp = pointer to EXTFS. -;--------------------------------------------------------------------- -proc ext2_lock - lea ecx, [ebp + EXTFS.lock] - jmp mutex_lock -endp - -;--------------------------------------------------------------------- -; Unlocks up an ext2 partition. -; Input: ebp = pointer to EXTFS. -;--------------------------------------------------------------------- -proc ext2_unlock - lea ecx, [ebp + EXTFS.lock] - jmp mutex_unlock -endp - -;--------------------------------------------------------------------- -; Check if it's a valid ext* superblock. -; Input: ebp: first three fields of PARTITION structure. -; ebx + 512: points to 512-bytes buffer that can be used for anything. -; Output: eax: clear if can't create partition; set to EXTFS otherwise. -;--------------------------------------------------------------------- -proc ext2_create_partition - push ebx - cmp dword [esi+DISK.MediaInfo.SectorSize], 512 - jnz .fail - - mov eax, 2 ; Superblock starts at 1024-bytes. - add ebx, 512 ; Get pointer to fs-specific buffer. - call fs_read32_sys - test eax, eax - jnz .fail - - ; Allowed 1KiB, 2KiB, 4KiB, 8KiB. - cmp [ebx + EXT2_SB_STRUC.log_block_size], 3 - ja .fail - - cmp [ebx + EXT2_SB_STRUC.magic], EXT2_SUPER_MAGIC - jne .fail - - cmp [ebx + EXT2_SB_STRUC.state], EXT2_VALID_FS - jne .fail - - ; Can't have no inodes per group. - cmp [ebx + EXT2_SB_STRUC.inodes_per_group], 0 - je .fail - - ; If incompatible features required, unusable superblock. - mov eax, [ebx + EXT2_SB_STRUC.feature_incompat] - test eax, not EXT4_FEATURE_INCOMPAT_SUPP - jz .setup - - .fail: - ; Not a (valid/usable) EXT2 superblock. - pop ebx - xor eax, eax - ret - - .setup: - movi eax, sizeof.EXTFS - call malloc - test eax, eax - jz ext2_create_partition.fail - - ; Store the first sector field. - mov ecx, dword[ebp + PARTITION.FirstSector] - mov dword[eax + EXTFS.FirstSector], ecx - mov ecx, dword [ebp + PARTITION.FirstSector+4] - mov dword [eax + EXTFS.FirstSector+4], ecx - - ; The length field. - mov ecx, dword[ebp + PARTITION.Length] - mov dword[eax + EXTFS.Length], ecx - mov ecx, dword[ebp + PARTITION.Length+4] - mov dword[eax + EXTFS.Length+4], ecx - - ; The disk field. - mov ecx, [ebp + PARTITION.Disk] - mov [eax + EXTFS.Disk], ecx - - mov [eax + EXTFS.FSUserFunctions], ext2_user_functions - - push ebp esi edi - - mov ebp, eax - lea ecx, [eax + EXTFS.lock] - call mutex_init - - ; Copy superblock from buffer to reserved memory. - mov esi, ebx - lea edi, [ebp + EXTFS.superblock] - mov ecx, 512/4 - rep movsd - - ; Get total groups. - mov eax, [ebx + EXT2_SB_STRUC.blocks_count] - sub eax, [ebx + EXT2_SB_STRUC.first_data_block] - dec eax - xor edx, edx - div [ebx + EXT2_SB_STRUC.blocks_per_group] - inc eax - mov [ebp + EXTFS.groups_count], eax - - ; Get log(block_size), such that 1,2,3,4 equ 1KiB,2KiB,4KiB,8KiB. - mov ecx, [ebx + EXT2_SB_STRUC.log_block_size] - inc ecx - mov [ebp + EXTFS.log_block_size], ecx - - ; 512-byte blocks in ext2 blocks. - mov eax, 1 - shl eax, cl - mov [ebp + EXTFS.count_block_in_block], eax - - ; Get block_size/4 (we'll find square later). - shl eax, 7 - mov [ebp + EXTFS.count_pointer_in_block], eax - mov edx, eax - - ; Get block size. - shl eax, 2 - mov [ebp + EXTFS.block_size], eax - - ; Save block size for 2 kernel_alloc calls. - push eax eax - - mov eax, edx - mul edx - mov [ebp + EXTFS.count_pointer_in_block_square], eax - - ; Have temporary block storage for get_inode procedure, and one for global procedure. - KERNEL_ALLOC [ebp + EXTFS.ext2_save_block], .error - KERNEL_ALLOC [ebp + EXTFS.ext2_temp_block], .error - - mov [ebp + EXTFS.partition_flags], 0x00000000 - mov eax, [ebx + EXT2_SB_STRUC.feature_ro_compat] - and eax, not EXT2_FEATURE_RO_COMPAT_SUPP - jnz .read_only - - mov eax, [ebx + EXT2_SB_STRUC.feature_incompat] - and eax, EXT4_FEATURE_INCOMPAT_W_NOT_SUPP - jz @F - - .read_only: - ; Mark as read-only. - or [ebp + EXTFS.partition_flags], EXT2_RO - @@: - mov ecx, [ebx + EXT2_SB_STRUC.blocks_per_group] - mov [ebp + EXTFS.blocks_per_group], ecx - - movzx ecx, word[ebx + EXT2_SB_STRUC.inode_size] - mov [ebp + EXTFS.inode_size], ecx - - ; Allocate for three inodes (loop would be overkill). - push ecx ecx ecx - - KERNEL_ALLOC [ebp + EXTFS.ext2_save_inode], .error - KERNEL_ALLOC [ebp + EXTFS.ext2_temp_inode], .error - KERNEL_ALLOC [ebp + EXTFS.root_inode], .error - - ; Read root inode. - mov ebx, eax - mov eax, EXT2_ROOT_INO - call ext2_inode_read - - test eax, eax - jnz .error - - ;call ext2_sb_update - ; Sync the disk. - ;mov esi, [ebp + PARTITION.Disk] - ;call disk_sync ; eax contains error code, if any. - - mov eax, ebp ; Return pointer to EXTFS. - pop edi esi ebp ebx - ret - - ; Error in setting up. - .error: - ; Free save block. - KERNEL_FREE [ebp + EXTFS.ext2_save_block], .fail - - ; Temporary block. - KERNEL_FREE [ebp + EXTFS.ext2_temp_block], .fail - - ; All inodes. - KERNEL_FREE [ebp + EXTFS.ext2_save_inode], .fail - KERNEL_FREE [ebp + EXTFS.ext2_temp_inode], .fail - KERNEL_FREE [ebp + EXTFS.root_inode], .fail - - mov eax, ebp - call free - - jmp .fail -endp - -; FUNCTIONS PROVIDED BY SYSCALLS. - -;--------------------------------------------------------------------- -; Frees up all ext2 structures. -; Input: eax = pointer to EXTFS. -;--------------------------------------------------------------------- -proc ext2_free - push ebp - - xchg ebp, eax - stdcall kernel_free, [ebp+EXTFS.ext2_save_block] - stdcall kernel_free, [ebp+EXTFS.ext2_temp_block] - stdcall kernel_free, [ebp+EXTFS.ext2_save_inode] - stdcall kernel_free, [ebp+EXTFS.ext2_temp_inode] - stdcall kernel_free, [ebp+EXTFS.root_inode] - - xchg ebp, eax - call free - - pop ebp - ret -endp - -;--------------------------------------------------------------------- -; Read disk folder. -; Input: ebp = pointer to EXTFS structure. -; esi + [esp + 4] = file name. -; ebx = pointer to parameters from sysfunc 70. -; Output: ebx = blocks read (or 0xFFFFFFFF, folder not found) -; eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_ReadFolder: - ;DEBUGF 1, "Reading folder.\n" - call ext2_lock - cmp byte [esi], 0 - jz .root_folder - - push ebx - stdcall ext2_inode_find, [esp + 4 + 4] ; Get inode. - pop ebx - - mov esi, [ebp + EXTFS.ext2_save_inode] - test eax, eax - jnz .error_ret - - ; If not a directory, then return with error. - test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR - jz .error_not_found - jmp @F - - .root_folder: - mov esi, [ebp + EXTFS.root_inode] - test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR - jz .error_root - - ; Copy the inode. - mov edi, [ebp + EXTFS.ext2_save_inode] - mov ecx, [ebp + EXTFS.inode_size] - shr ecx, 2 - - push edi - rep movsd - pop esi - - @@: - cmp [esi + EXT2_INODE_STRUC.i_size], 0 ; Folder is empty. - je .error_empty_dir - - mov edx, [ebx + 16] - push edx ; Result address [edi + 28]. - push 0 ; End of the current block in folder [edi + 24] - push dword[ebx + 12] ; Blocks to read [edi + 20] - push dword[ebx + 4] ; The first wanted file [edi + 16] - push dword[ebx + 8] ; Flags [edi + 12] - push 0 ; Read files [edi + 8] - push 0 ; Files in folder [edi + 4] - push 0 ; Number of blocks read in dir (and current block index) [edi] - - ; Fill header with zeroes. - mov edi, edx - mov ecx, 32/4 - rep stosd - - mov edi, esp ; edi = pointer to local variables. - add edx, 32 ; edx = mem to return. - - xor ecx, ecx ; Get number of first block. - call ext2_inode_get_block - test eax, eax - jnz .error_get_block - - mov eax, ecx - mov ebx, [ebp + EXTFS.ext2_save_block] - call ext2_block_read ; Read the block. - test eax, eax - jnz .error_get_block - - mov eax, ebx ; esi: current directory record - add eax, [ebp + EXTFS.block_size] - - mov [edi + 24], eax - - mov ecx, [edi + 16] ; ecx = first wanted (flags ommited) - - .find_wanted_start: - jecxz .find_wanted_end - - .find_wanted_cycle: - cmp [ebx + EXT2_DIR_STRUC.inode], 0 ; Don't count unused inode in total files. - jz @F - - inc dword [edi + 4] ; EXT2 files in folder. - dec ecx - @@: - movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] - - cmp eax, 12 ; Minimum record length. - jb .error_bad_len - test eax, 0x3 ; Record length must be divisible by four. - jnz .error_bad_len - - sub [esi + EXT2_INODE_STRUC.i_size], eax ; Subtract "processed record" length directly from inode. - add ebx, eax ; Go to next record. - cmp ebx, [edi + 24] ; If not reached the next block, continue. - jb .find_wanted_start - - push .find_wanted_start - .end_block: ; Get the next block. - cmp [esi + EXT2_INODE_STRUC.i_size], 0 - jle .end_dir - - inc dword [edi] ; Number of blocks read. - - ; Read the next block. - push ecx - mov ecx, [edi] - call ext2_inode_get_block - test eax, eax - jnz .error_get_block - - mov eax, ecx - mov ebx, [ebp + EXTFS.ext2_save_block] - call ext2_block_read - test eax, eax - jnz .error_get_block - pop ecx - - mov eax, ebx - add eax, [ebp + EXTFS.block_size] - mov [edi + 24], eax ; Update the end of the current block variable. - ret - - .wanted_end: - loop .find_wanted_cycle ; Skip files till we reach wanted one. - - ; First requisite file. - .find_wanted_end: - mov ecx, [edi + 20] - .wanted_start: ; Look for first_wanted + count. - jecxz .wanted_end - - cmp [ebx + EXT2_DIR_STRUC.inode], 0 ; if (inode == 0): not used; - jz .empty_rec - - ; Increment "files in dir" and "read files" count. - inc dword [edi + 8] - inc dword [edi + 4] - - push edi ecx - mov edi, edx ; Zero out till the name field. - xor eax, eax - mov ecx, 40 / 4 - rep stosd - pop ecx edi - - push ebx edi edx - mov eax, [ebx + EXT2_DIR_STRUC.inode] ; Get the child inode. - mov ebx, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_read - test eax, eax - jnz .error_read_subinode - - lea edi, [edx + 8] - - mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] ; Convert time in NTFS format. - xor edx, edx - add eax, 3054539008 ; (369 * 365 + 89) * 24 * 3600 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec - - mov eax, [ebx + EXT2_INODE_STRUC.i_atime] - xor edx, edx - add eax, 3054539008 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec - - mov eax, [ebx + EXT2_INODE_STRUC.i_mtime] - xor edx, edx - add eax, 3054539008 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec - - pop edx - test [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; If folder, don't report size. - jnz @F - - mov eax, [ebx + EXT2_INODE_STRUC.i_size] ; Low size - stosd - mov eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ; High size - stosd - - xor dword [edx], FS_FT_DIR ; Mark as file. - @@: - xor dword [edx], FS_FT_DIR ; Mark as directory. - - ; Copy name after converting from UTF-8 to CP866. - push ecx esi - mov esi, [esp + 12] - movzx ecx, [esi + EXT2_DIR_STRUC.name_len] - lea edi, [edx + 40] - lea esi, [esi + EXT2_DIR_STRUC.name] - call utf8_to_cp866 - and byte [edi], 0 - pop esi ecx edi ebx - - cmp byte [edx + 40], '.' ; If it begins with ".", mark it as hidden. - jne @F - or dword [edx], FS_FT_HIDDEN - - @@: - add edx, 40 + 264 ; Go to next record. - dec ecx - .empty_rec: - movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] - - cmp eax, 12 ; Illegal length. - jb .error_bad_len - test eax, 0x3 ; Not a multiple of four. - jnz .error_bad_len - - sub [esi + EXT2_INODE_STRUC.i_size], eax ; Subtract directly from the inode. - add ebx, eax - cmp ebx, [edi + 24] ; Are we at the end of the block? - jb .wanted_start - - push .wanted_start - jmp .end_block - - .end_dir: ; End of the directory. - call ext2_unlock - mov edx, [edi + 28] ; Address of where to return data. - mov ebx, [edi + 8] ; EXT2_read_in_folder - mov ecx, [edi + 4] ; EXT2_files_in_folder - mov dword [edx], 1 ; Version - mov [edx + 4], ebx - mov [edx + 8], ecx - - lea esp, [edi + 32] - - xor eax, eax ; Reserved in current implementation. - lea edi, [edx + 12] - mov ecx, 20 / 4 - rep stosd - - ;DEBUGF 1, "Returning with: %x.\n", eax - ret - - .error_bad_len: - mov eax, ERROR_FS_FAIL - - .error_read_subinode: - .error_get_block: - ; Fix the stack. - lea esp, [edi + 32] - - .error_ret: - or ebx, -1 - push eax - call ext2_unlock - pop eax - ;DEBUGF 1, "Returning with: %x.\n", eax - ret - - .error_empty_dir: ; inode of folder without blocks. - .error_root: ; Root has to be a folder. - mov eax, ERROR_FS_FAIL - jmp .error_ret - - .error_not_found: ; Directory not found. - mov eax, ERROR_FILE_NOT_FOUND - jmp .error_ret - -;--------------------------------------------------------------------- -; Read file from the hard disk. -; Input: esi + [esp + 4] = points to file name. -; ebx = pointer to paramteres from sysfunc 70. -; ebp = pointer to EXTFS structure. -; Output: ebx = bytes read (0xFFFFFFFF -> file not found) -; eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_Read: - ;DEBUGF 1, "Attempting read.\n" - call ext2_lock - cmp byte [esi], 0 - jnz @F - - .this_is_nofile: - call ext2_unlock - or ebx, -1 - mov eax, ERROR_ACCESS_DENIED - ret - - @@: - push ebx - stdcall ext2_inode_find, [esp + 4 + 4] - pop ebx - - mov esi, [ebp + EXTFS.ext2_save_inode] - test eax, eax - jz @F - - call ext2_unlock - or ebx, -1 - mov eax, ERROR_FILE_NOT_FOUND - ret - - @@: - mov ax, [esi + EXT2_INODE_STRUC.i_mode] - and ax, EXT2_S_IFMT ; Leave the file format in AX. - - ; Check if file. - cmp ax, EXT2_S_IFREG - jne .this_is_nofile - - mov edi, [ebx + 16] - mov ecx, [ebx + 12] - - mov eax, [ebx + 4] - mov edx, [ebx + 8] ; edx:eax = start byte number. - - ; Check if file is big enough for us. - cmp [esi + EXT2_INODE_STRUC.i_dir_acl], edx - ja .size_greater - jb .size_less - - cmp [esi + EXT2_INODE_STRUC.i_size], eax - ja .size_greater - - .size_less: - call ext2_unlock - xor ebx, ebx - mov eax, ERROR_END_OF_FILE - ret - - @@: - .size_greater: - add eax, ecx ; Get last byte. - adc edx, 0 - - ; Check if we've to read whole file, or till requested. - cmp [esi + EXT2_INODE_STRUC.i_dir_acl], edx - ja .read_till_requested - jb .read_whole_file - cmp [esi + EXT2_INODE_STRUC.i_size], eax - jae .read_till_requested - - .read_whole_file: - push 1 ; Read till the end of file. - mov ecx, [esi + EXT2_INODE_STRUC.i_size] - sub ecx, [ebx + 4] ; To read = (size - starting byte) - jmp @F - - .read_till_requested: - push 0 ; Read as much as requested. - - @@: - ; ecx = bytes to read. - ; edi = return memory - ; [esi] = starting byte. - - push ecx ; Number of bytes to read. - - ; Get part of the first block. - mov edx, [ebx + 8] - mov eax, [ebx + 4] - div [ebp + EXTFS.block_size] - - push eax ; Save block counter to stack. - - push ecx - mov ecx, eax - call ext2_inode_get_block - test eax, eax - jnz .error_at_first_block - - mov ebx, [ebp + EXTFS.ext2_save_block] - mov eax, ecx - call ext2_block_read - test eax, eax - jnz .error_at_first_block - - pop ecx - ; Get index inside block. - add ebx, edx - - neg edx - add edx, [ebp + EXTFS.block_size] ; Get number of bytes in this block. - - ; If it's smaller than total bytes to read, then only one block. - cmp ecx, edx - jbe .only_one_block - - mov eax, ecx - sub eax, edx - mov ecx, edx - - push esi - mov esi, ebx - rep movsb ; Copy part of 1st block. - pop esi - - ; eax -> bytes to read. - .calc_blocks_count: - mov ebx, edi ; Read the block in ebx. - xor edx, edx - div [ebp + EXTFS.block_size] ; Get number of bytes in last block in edx. - mov edi, eax ; Get number of blocks in edi. - - @@: - ; Test if all blocks are done. - test edi, edi - jz .finish_block - - inc dword [esp] - mov ecx, [esp] - call ext2_inode_get_block - - test eax, eax - jnz .error_at_read_cycle - - mov eax, ecx ; ebx already contains desired values. - call ext2_block_read - - test eax, eax - jnz .error_at_read_cycle - - add ebx, [ebp + EXTFS.block_size] - - dec edi - jmp @B - - ; In edx -- number of bytes in the last block. - .finish_block: - test edx, edx - jz .end_read - - pop ecx ; Pop block counter in ECX. - inc ecx - call ext2_inode_get_block - - test eax, eax - jnz .error_at_finish_block - - mov edi, ebx - mov eax, ecx - mov ebx, [ebp + EXTFS.ext2_save_block] - call ext2_block_read - - test eax, eax - jnz .error_at_finish_block - - mov ecx, edx - mov esi, ebx - rep movsb ; Copy last piece of block. - jmp @F - - .end_read: - pop ecx ; Pop block counter in ECX. - @@: - pop ebx ; Number of bytes read. - call ext2_unlock - pop eax ; If we were asked to read more, say EOF. - test eax, eax - jz @F - - mov eax, ERROR_END_OF_FILE - ret - @@: - xor eax, eax - ;DEBUGF 1, "Returning with: %x.\n", eax - ret - - .only_one_block: - mov esi, ebx - rep movsb ; Copy last piece of block. - jmp .end_read - - .error_at_first_block: - pop edx - .error_at_read_cycle: - pop ebx - .error_at_finish_block: - pop ecx edx - or ebx, -1 - push eax - call ext2_unlock - pop eax - - ;DEBUGF 1, "Returning with: %x.\n", eax - ret - -;--------------------------------------------------------------------- -; Read file information from block device. -; Input: esi + [esp + 4] = file name. -; ebx = pointer to paramteres from sysfunc 70. -; ebp = pointer to EXTFS structure. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_GetFileInfo: - ;DEBUGF 1, "Calling for file info, for: %s.\n", esi - call ext2_lock - mov edx, [ebx + 16] - cmp byte [esi], 0 - jz .is_root - - push edx - stdcall ext2_inode_find, [esp + 4 + 4] - mov ebx, edx - pop edx - - mov esi, [ebp + EXTFS.ext2_save_inode] - test eax, eax - jz @F - - push eax - call ext2_unlock - pop eax - ;DEBUGF 1, "Returning with: %x.\n", eax - ret - - .is_root: - xor ebx, ebx ; Clear out first char, since we don't want to set hidden flag on root. - mov esi, [ebp + EXTFS.root_inode] - - @@: - xor eax, eax - mov edi, edx - mov ecx, 40/4 - rep stosd ; Zero fill buffer. - - cmp bl, '.' - jne @F - or dword [edx], FS_FT_HIDDEN - - @@: - test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR - jnz @F ; If a directory, don't put in file size. - - mov eax, [esi + EXT2_INODE_STRUC.i_size] ; Low file size. - mov ebx, [esi + EXT2_INODE_STRUC.i_dir_acl] ; High file size. - mov dword [edx+32], eax - mov dword [edx+36], ebx - - xor dword [edx], FS_FT_DIR ; Next XOR will clean this, to mark it as a file. - @@: - xor dword [edx], FS_FT_DIR ; Mark as directory. - - lea edi, [edx + 8] - - ; Store all time. - mov eax, [esi + EXT2_INODE_STRUC.i_ctime] - xor edx, edx - add eax, 3054539008 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec - - mov eax, [esi + EXT2_INODE_STRUC.i_atime] - xor edx, edx - add eax, 3054539008 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec - - mov eax, [esi + EXT2_INODE_STRUC.i_mtime] - xor edx, edx - add eax, 3054539008 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec - - call ext2_unlock - xor eax, eax - ;DEBUGF 1, "Returning with: %x.\n", eax - ret - -;--------------------------------------------------------------------- -; Set file information for block device. -; Input: esi + [esp + 4] = file name. -; ebx = pointer to paramteres from sysfunc 70. -; ebp = pointer to EXTFS structure. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_SetFileInfo: - test [ebp + EXTFS.partition_flags], EXT2_RO - jz @F - - mov eax, ERROR_UNSUPPORTED_FS - ret - - @@: - push edx esi edi ebx - call ext2_lock - mov edx, [ebx + 16] - - ; Is this read-only? - test [ebp + EXTFS.partition_flags], EXT2_RO - jnz .fail - - ; Not supported for root. - cmp byte [esi], 0 - je .fail - - .get_inode: - push edx - stdcall ext2_inode_find, [esp + 4 + 20] - pop edx - - test eax, eax - jnz @F - - ; Save inode number. - push esi - mov esi, [ebp + EXTFS.ext2_save_inode] - - ; From the BDFE, we ignore read-only file flags, hidden file flags; - ; We ignore system file flags, file was archived or not. - - ; Also ignored is file creation time. ext2 stores "inode modification" - ; time in the ctime field, which is updated by the respective inode_write - ; procedure, and any writes on it would be overwritten anyway. - - ; Access time. - lea edi, [esi + EXT2_INODE_STRUC.i_atime] - lea esi, [edx + 16] - call bdfe_to_unix_time - - ; Modification time. - add esi, 8 - add edi, 8 - call bdfe_to_unix_time - - mov ebx, [ebp + EXTFS.ext2_save_inode] ; Get address of inode into ebx. - pop eax ; Get inode number in eax. - call ext2_inode_write ; eax contains error code, if any. - test eax, eax - jnz @F - - call ext2_sb_update - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - @@: - push eax - call ext2_unlock - pop eax - - pop ebx edi esi edx - ret - - .fail: - call ext2_sb_update - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - mov eax, ERROR_UNSUPPORTED_FS - jmp @B - -;--------------------------------------------------------------------- -; Set file information for block device. -; Input: esi + [esp + 4] = file name. -; ebx = pointer to paramteres from sysfunc 70. -; ebp = pointer to EXTFS structure. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_Delete: - ;DEBUGF 1, "Attempting Delete.\n" - test [ebp + EXTFS.partition_flags], EXT2_RO - jz @F - - mov eax, ERROR_UNSUPPORTED_FS - ret - - @@: - push ebx ecx edx esi edi - call ext2_lock - - add esi, [esp + 20 + 4] - - ; Can't delete root. - cmp byte [esi], 0 - jz .error_access_denied - - push esi - stdcall ext2_inode_find, 0 - mov ebx, esi - pop esi - - test eax, eax - jnz .error_access_denied - - mov edx, [ebp + EXTFS.ext2_save_inode] - movzx edx, [edx + EXT2_INODE_STRUC.i_mode] - and edx, EXT2_S_IFMT ; Get the mask. - cmp edx, EXT2_S_IFDIR - jne @F ; If not a directory, we don't need to check if it's empty. - - call ext2_dir_empty ; 0 means directory is empty. - - test eax, eax - jnz .error_access_denied - - @@: - ; Find parent. - call ext2_inode_find_parent - test eax, eax - jnz .error_access_denied - mov eax, esi - - ; Save file/dir & parent inode. - push ebx eax - - cmp edx, EXT2_S_IFDIR - jne @F - - ; Unlink '.' - mov eax, [esp + 4] - call ext2_inode_unlink - cmp eax, 0xFFFFFFFF - je .error_stack8 - - ; Unlink '..' - mov eax, [esp + 4] - mov ebx, [esp] - call ext2_inode_unlink - cmp eax, 0xFFFFFFFF - je .error_stack8 - - @@: - pop eax - mov ebx, [esp] - ; Unlink the inode. - call ext2_inode_unlink - cmp eax, 0xFFFFFFFF - je .error_stack4 - - ; If hardlinks aren't zero, shouldn't completely free. - test eax, eax - jz @F - - add esp, 4 - jmp .disk_sync - - @@: - ; Read the inode. - mov eax, [esp] - mov ebx, [ebp + EXTFS.ext2_save_inode] - call ext2_inode_read - test eax, eax - jnz .error_stack4 - - ; Free inode data. - mov esi, [ebp + EXTFS.ext2_save_inode] - xor ecx, ecx - - @@: - push ecx - call ext2_inode_get_block - test eax, eax - jnz .error_stack8 - mov eax, ecx - pop ecx - - ; If 0, we're done. - test eax, eax - jz @F - - call ext2_block_free - test eax, eax - jnz .error_stack4 - - inc ecx - jmp @B - - @@: - ; Free indirect blocks. - call ext2_inode_free_indirect_blocks - test eax, eax - jnz .error_stack4 - - ; Clear the inode, and add deletion time. - mov edi, [ebp + EXTFS.ext2_save_inode] - xor eax, eax - mov ecx, [ebp + EXTFS.inode_size] - rep stosb - - mov edi, [ebp + EXTFS.ext2_save_inode] - add edi, EXT2_INODE_STRUC.i_dtime - call current_unix_time - - ; Write the inode. - mov eax, [esp] - mov ebx, [ebp + EXTFS.ext2_save_inode] - call ext2_inode_write - test eax, eax - jnz .error_stack4 - - ; Check if directory. - cmp edx, EXT2_S_IFDIR - jne @F - - ; If it is, decrement used_dirs_count. - - ; Get block group. - mov eax, [esp] - dec eax - xor edx, edx - div [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group] - - push eax - call ext2_bg_read_desc - test eax, eax - jz .error_stack8 - - dec [eax + EXT2_BLOCK_GROUP_DESC.used_dirs_count] - - pop eax - call ext2_bg_write_desc - - @@: - pop eax - call ext2_inode_free - test eax, eax - jnz .error_access_denied - - .disk_sync: - call ext2_sb_update - - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - .return: - push eax - call ext2_unlock - pop eax - - pop edi esi edx ecx ebx - ;DEBUGF 1, "And returning with: %x.\n", eax - ret - - .error_stack8: - add esp, 4 - .error_stack4: - add esp, 4 - .error_access_denied: - call ext2_sb_update - - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - mov eax, ERROR_ACCESS_DENIED - jmp .return - -;--------------------------------------------------------------------- -; Set file information for block device. -; Input: esi + [esp + 4] = file name. -; ebx = pointer to paramteres from sysfunc 70. -; ebp = pointer to EXTFS structure. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_CreateFolder: - ;DEBUGF 1, "Attempting to create folder.\n" - test [ebp + EXTFS.partition_flags], EXT2_RO - jz @F - - mov eax, ERROR_UNSUPPORTED_FS - ret - - @@: - push ebx ecx edx esi edi - call ext2_lock - - add esi, [esp + 20 + 4] - - ; Can't create root, but for CreateFolder already existing directory is success. - cmp byte [esi], 0 - jz .success - - push esi - stdcall ext2_inode_find, 0 - pop esi - - ; If the directory is there, we've succeeded. - test eax, eax - jz .success - - ; Find parent. - call ext2_inode_find_parent - test eax, eax - jnz .error - - ; Inode ID for preference. - mov eax, esi - call ext2_inode_alloc - test eax, eax - jnz .error_full - - ; Save allocated inode in EDX; filename is in EDI; parent ID in ESI. - mov edx, ebx - - push edi - - xor al, al - mov edi, [ebp + EXTFS.ext2_temp_inode] - mov ecx, [ebp + EXTFS.inode_size] - rep stosb - - mov edi, [ebp + EXTFS.ext2_temp_inode] - add edi, EXT2_INODE_STRUC.i_atime - call current_unix_time - - add edi, 8 - call current_unix_time - - pop edi - - mov ebx, [ebp + EXTFS.ext2_temp_inode] - mov [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR or PERMISSIONS - mov eax, edx - call ext2_inode_write - test eax, eax - jnz .error - - ; Link to self. - push edx esi - - mov eax, edx - mov ebx, eax - mov dl, EXT2_FT_DIR - mov esi, self_link - call ext2_inode_link - - pop esi edx - - test eax, eax - jnz .error - - ; Link to parent. - push edx esi - - mov eax, ebx - mov ebx, esi - mov dl, EXT2_FT_DIR - mov esi, parent_link - call ext2_inode_link - - pop esi edx - - test eax, eax - jnz .error - - ; Link parent to child. - mov eax, esi - mov ebx, edx - mov esi, edi - mov dl, EXT2_FT_DIR - call ext2_inode_link - test eax, eax - jnz .error - - ; Get block group descriptor for allocated inode's block. - mov eax, ebx - dec eax - xor edx, edx - - ; EAX = block group. - div [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group] - mov edx, eax - - call ext2_bg_read_desc - test eax, eax - jz .error - - inc [eax + EXT2_BLOCK_GROUP_DESC.used_dirs_count] - mov eax, edx - call ext2_bg_write_desc - test eax, eax - jnz .error - - .success: - call ext2_sb_update - - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - .return: - push eax - call ext2_unlock - pop eax - - pop edi esi edx ecx ebx - ;DEBUGF 1, "Returning with: %x.\n", eax - ret - - .error: - call ext2_sb_update - - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - mov eax, ERROR_ACCESS_DENIED - jmp .return - - .error_full: - mov eax, ERROR_DISK_FULL - jmp .return - -self_link db ".", 0 -parent_link db "..", 0 - -;--------------------------------------------------------------------- -; Rewrite a file. -; Input: esi + [esp + 4] = file name. -; ebx = pointer to paramteres from sysfunc 70. -; ebp = pointer to EXTFS structure. -; Output: eax = error code. -; ebx = bytes written. -;--------------------------------------------------------------------- -ext2_Rewrite: - ;DEBUGF 1, "Attempting Rewrite.\n" - test [ebp + EXTFS.partition_flags], EXT2_RO - jz @F - - mov eax, ERROR_UNSUPPORTED_FS - ret - - @@: - push ecx edx esi edi - pushad - - call ext2_lock - - add esi, [esp + 16 + 32 + 4] - ; Can't create root. - cmp byte [esi], 0 - jz .error_access_denied - - push esi - stdcall ext2_inode_find, 0 - pop esi - - ; If the file is there, delete it. - test eax, eax - jnz @F - - pushad - - push eax - call ext2_unlock - pop eax - - push dword 0x00000000 - call ext2_Delete - add esp, 4 - - push eax - call ext2_lock - pop eax - - test eax, eax - jnz .error_access_denied_delete - - popad - @@: - ; Find parent. - call ext2_inode_find_parent - test eax, eax - jnz .error_access_denied - - ; Inode ID for preference. - mov eax, esi - call ext2_inode_alloc - test eax, eax - jnz .error_full - - ; Save allocated inode in EDX; filename is in EDI; parent ID in ESI. - mov edx, ebx - - push edi - - xor al, al - mov edi, [ebp + EXTFS.ext2_temp_inode] - mov ecx, [ebp + EXTFS.inode_size] - rep stosb - - mov edi, [ebp + EXTFS.ext2_temp_inode] - add edi, EXT2_INODE_STRUC.i_atime - call current_unix_time - - add edi, 8 - call current_unix_time - - pop edi - - mov ebx, [ebp + EXTFS.ext2_temp_inode] - mov [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG or PERMISSIONS - mov eax, edx - call ext2_inode_write - test eax, eax - jnz .error - - ; Link parent to child. - mov eax, esi - mov ebx, edx - mov esi, edi - mov dl, EXT2_FT_REG_FILE - call ext2_inode_link - test eax, eax - jnz .error - - popad - push eax - call ext2_unlock - pop eax - - push dword 0x00000000 - call ext2_Write - add esp, 4 - - push eax - call ext2_lock - pop eax - - .success: - push eax - call ext2_sb_update - - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - pop eax - - .return: - push eax - call ext2_unlock - pop eax - - pop edi esi edx ecx - - ;DEBUGF 1, "And returning with: %x.\n", eax - ret - - .error: - mov eax, ERROR_ACCESS_DENIED - jmp .success - - .error_access_denied_delete: - popad - - .error_access_denied: - popad - xor ebx, ebx - - mov eax, ERROR_ACCESS_DENIED - jmp .return - - .error_full: - popad - xor ebx, ebx - - mov eax, ERROR_DISK_FULL - jmp .return - -;--------------------------------------------------------------------- -; Write to a file. -; Input: esi + [esp + 4] = file name. -; ebx = pointer to paramteres from sysfunc 70. -; ebp = pointer to EXTFS structure. -; Output: eax = error code. -; ebx = number of bytes written. -;--------------------------------------------------------------------- -ext2_Write: - ;DEBUGF 1, "Attempting write, " - test [ebp + EXTFS.partition_flags], EXT2_RO - jz @F - - mov eax, ERROR_UNSUPPORTED_FS - ret - - @@: - push ecx edx esi edi - call ext2_lock - - add esi, [esp + 16 + 4] - - ; Can't write to root. - cmp byte [esi], 0 - jz .error - - push ebx ecx edx - stdcall ext2_inode_find, 0 - pop edx ecx ebx - ; If file not there, error. - xor ecx, ecx - test eax, eax - jnz .error_file_not_found - - ; Save the inode. - push esi - - ; Check if it's a file. - mov edx, [ebp + EXTFS.ext2_save_inode] - test [edx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG - jz .error - - mov eax, esi - mov ecx, [ebx + 4] - - call ext2_inode_extend - xor ecx, ecx - test eax, eax - jnz .error_device - - ; ECX contains the size to write, and ESI points to it. - mov ecx, [ebx + 0x0C] - mov esi, [ebx + 0x10] - - ; Save the size of the inode. - mov eax, [edx + EXT2_INODE_STRUC.i_size] - push eax - - xor edx, edx - div [ebp + EXTFS.block_size] - - test edx, edx - jz .start_aligned - - ; Start isn't aligned, so deal with the non-aligned bytes. - mov ebx, [ebp + EXTFS.block_size] - sub ebx, edx - - cmp ebx, ecx - jbe @F - - ; If the size to copy fits in current block, limit to that, instead of the entire block. - mov ebx, ecx - - @@: - ; Copy EBX bytes, in EAX indexed block. - push eax - call ext2_inode_read_entry - test eax, eax - pop eax - jnz .error_inode_size - - push ecx - - mov ecx, ebx - mov edi, ebx - add edi, edx - rep movsb - - pop ecx - - ; Write the block. - call ext2_inode_write_entry - test eax, eax - jnz .error_inode_size - - add [esp], ebx - sub ecx, ebx - jz .write_inode - - .start_aligned: - cmp ecx, [ebp + EXTFS.block_size] - jb @F - - mov eax, [esp] - xor edx, edx - div [ebp + EXTFS.block_size] - - push eax - mov edx, [esp + 8] - call ext2_inode_blank_entry - test eax, eax - pop eax - jnz .error_inode_size - - push ecx - - mov ecx, [ebp + EXTFS.block_size] - mov edi, [ebp + EXTFS.ext2_save_block] - rep movsb - - pop ecx - - call ext2_inode_write_entry - test eax, eax - jnz .error_inode_size - - mov eax, [ebp + EXTFS.block_size] - sub ecx, eax - add [esp], eax - jmp .start_aligned - - ; Handle the remaining bytes. - @@: - test ecx, ecx - jz .write_inode - - mov eax, [esp] - xor edx, edx - div [ebp + EXTFS.block_size] - - push eax - call ext2_inode_read_entry - test eax, eax - pop eax - jz @F - - push eax - mov edx, [esp + 8] - - call ext2_inode_blank_entry - test eax, eax - pop eax - jnz .error_inode_size - - @@: - push ecx - mov edi, [ebp + EXTFS.ext2_save_block] - rep movsb - pop ecx - - call ext2_inode_write_entry - test eax, eax - jnz .error_inode_size - - add [esp], ecx - xor ecx, ecx - - .write_inode: - mov ebx, [ebp + EXTFS.ext2_temp_inode] - pop eax - mov [ebx + EXT2_INODE_STRUC.i_size], eax - mov eax, [esp] - - call ext2_inode_write - test eax, eax - jnz .error_device - - .success: - call ext2_sb_update - - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - .return: - push eax - call ext2_unlock - pop eax - - add esp, 4 - - mov ebx, [esp + 12] - sub ebx, ecx - pop edi esi edx ecx - - ;DEBUGF 1, "and returning with: %x.\n", eax - ret - - .error: - mov eax, ERROR_ACCESS_DENIED - jmp .return - - .error_file_not_found: - mov eax, ERROR_FILE_NOT_FOUND - jmp .return - - .error_inode_size: - mov ebx, [ebp + EXTFS.ext2_temp_inode] - pop eax - mov [ebx + EXT2_INODE_STRUC.i_size], eax - mov eax, [esp] - - call ext2_inode_write - - .error_device: - call ext2_sb_update - - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - mov eax, ERROR_DEVICE - jmp .return - -;--------------------------------------------------------------------- -; Set the end of a file. -; Input: esi + [esp + 4] = file name. -; ebx = pointer to paramteres from sysfunc 70. -; ebp = pointer to EXTFS structure. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_SetFileEnd: - test [ebp + EXTFS.partition_flags], EXT2_RO - jz @F - - mov eax, ERROR_UNSUPPORTED_FS - ret - - @@: - push ebx ecx edx esi edi - call ext2_lock - - add esi, [esp + 20 + 4] - - ; Can't write to root. - cmp byte [esi], 0 - jz .error - - stdcall ext2_inode_find, 0 - ; If file not there, error. - test eax, eax - jnz .error_file_not_found - - ; Check if it's a file. - mov edx, [ebp + EXTFS.ext2_save_inode] - cmp [edx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG - jne .error - - mov eax, esi - mov ecx, [ebx + 4] - call ext2_inode_extend - test eax, eax - jnz .error_disk_full - - mov eax, esi - call ext2_inode_truncate - test eax, eax - jnz .error_disk_full - - mov eax, esi - mov ebx, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_write - - call ext2_sb_update - - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - .return: - push eax - call ext2_unlock - pop eax - - pop edi esi edx ecx ebx - ret - - .error: - mov eax, ERROR_ACCESS_DENIED - jmp .return - - .error_file_not_found: - mov eax, ERROR_FILE_NOT_FOUND - jmp .return - - .error_disk_full: - call ext2_sb_update - - ; Sync the disk. - mov esi, [ebp + PARTITION.Disk] - call disk_sync ; eax contains error code, if any. - - mov eax, ERROR_DISK_FULL - jmp .return diff --git a/kernel/trunk/fs/ext2/ext2.inc b/kernel/trunk/fs/ext2/ext2.inc deleted file mode 100644 index dfcbb9212d..0000000000 --- a/kernel/trunk/fs/ext2/ext2.inc +++ /dev/null @@ -1,673 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Contains ext2 structures, and macros. ;; -;; ;; -;; Copyright (C) KolibriOS team 2013-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; Future jobs for driver, in order of preference: -; * clean up existing extents support. -; * add b-tree directories support. -; * add long file support. -; * add journal support. -; * add minor features that come with ext3/4. - -; Recommended move to some kernel-wide bitmap handling code (with a bit of abstraction, of course). - -;--------------------------------------------------------------------- -; Clears a bit. -; Input: eax = index into bitmap. -; [EXTFS.ext2_save_block] = address of bitmap. -; ebp = address of EXTFS. -; Output: Bit cleared. -; eax = non-zero, if already cleared. -;--------------------------------------------------------------------- -bitmap_clear_bit: - push ebx ecx edx - - xor edx, edx - mov ecx, 8 - div ecx - - add eax, [ebp + EXTFS.ext2_save_block] - - ; Get the mask. - mov ebx, 1 - mov ecx, edx - shl ebx, cl - - test [eax], ebx - jz .cleared - - not ebx - and [eax], ebx - - xor eax, eax - .return: - pop edx ecx ebx - ret - - ; Already cleared. - .cleared: - xor eax, eax - not eax - jmp .return - -;--------------------------------------------------------------------- -; Finds free bit in the bitmap. -; Input: ecx = number of bits in the bitmap. -; [EXTFS.ext2_save_block] = address of bitmap. -; ebp = address of EXTFS. -; Output: eax = index of free bit in the bitmap; marked set. -; 0xFFFFFFFF if no free bit found. -;--------------------------------------------------------------------- -ext2_find_free_bit: -bitmap_find_free_bit: - push esi ebx ecx edx - mov esi, [ebp + EXTFS.ext2_save_block] - - ; Get total DWORDS in eax; total bits in last dword, if any, in edx. - xor edx, edx - mov eax, ecx - mov ecx, 32 - div ecx - - mov ecx, eax - xor eax, eax - push edx - - test ecx, ecx - jz .last_bits - - ; Check in the DWORDS. - .dwords: - mov ebx, [esi] - not ebx - - bsf edx, ebx - - ; If 0, then the original value would be 0xFFFFFFFF, hence no free bits. - jz @F - - ; We found the value. Let's return with it. - add esp, 4 - - add eax, edx - jmp .return - - @@: - add esi, 4 - add eax, 32 - loop .dwords - - .last_bits: - ; Check in the last few bits. - pop ecx - test ecx, ecx - jz @F - - mov ebx, [esi] - not ebx - bsf ebx, edx - - ; If 0, no free bits. - jz @F - - ; If free bit is greater than the last known bit, then error. - cmp edx, ecx - jg @F - - add eax, edx - jmp .return - - @@: - ; Didn't find any free bits. - xor eax, eax - not eax - jmp @F - - .return: - mov ecx, edx - mov edx, 1 - shl edx, cl - or [esi], edx - - @@: - pop edx ecx ebx esi - ret - -; Recommended move to some kernel-wide string handling code. -;--------------------------------------------------------------------- -; Find the length of a string. -; Input: esi = source. -; Output: length in ecx -;--------------------------------------------------------------------- -strlen: - push eax esi - xor ecx, ecx - - @@: - lodsb - test al, al - jz .ret - - inc ecx - jmp @B - - .ret: - pop esi eax - ret - -;--------------------------------------------------------------------- -; Convert UTF-8 string to ASCII-string (codepage 866) -; Input: esi = source. -; edi = buffer. -; ecx = length of source. -; Output: destroys eax, esi, edi -;--------------------------------------------------------------------- -utf8_to_cp866: - ; Check for zero-length string. - jecxz .return - - .start: - lodsw - cmp al, 0x80 - jb .ascii - - xchg al, ah ; Big-endian. - cmp ax, 0xd080 - jz .yo1 - - cmp ax, 0xd191 - jz .yo2 - - cmp ax, 0xd090 - jb .unk - - cmp ax, 0xd180 - jb .rus1 - - cmp ax, 0xd190 - jb .rus2 - - .unk: - mov al, '_' - jmp .doit - - .yo1: - mov al, 0xf0 ; Ё capital. - jmp .doit - - .yo2: - mov al, 0xf1 ; ё small. - jmp .doit - - .rus1: - sub ax, 0xd090 - 0x80 - jmp .doit - - .rus2: - sub ax, 0xd18f - 0xEF - - .doit: - stosb - sub ecx, 2 - ja .start - ret - - .ascii: - stosb - dec esi - dec ecx - jnz .start - - .return: - ret - -; Recommended move to some kernel-wide time handling code. - -; Total cumulative seconds till each month. -cumulative_seconds_in_month: - .january: dd 0 * (60 * 60 * 24) - .february: dd 31 * (60 * 60 * 24) - .march: dd 59 * (60 * 60 * 24) - .april: dd 90 * (60 * 60 * 24) - .may: dd 120 * (60 * 60 * 24) - .june: dd 151 * (60 * 60 * 24) - .july: dd 181 * (60 * 60 * 24) - .august: dd 212 * (60 * 60 * 24) - .september: dd 243 * (60 * 60 * 24) - .october: dd 273 * (60 * 60 * 24) - .november: dd 304 * (60 * 60 * 24) - .december: dd 334 * (60 * 60 * 24) - -current_bdfe_time: - dd 0 -current_bdfe_date: - dd 0 - -;--------------------------------------------------------------------- -; Stores current unix time. -; Input: edi = buffer to output Unix time. -;--------------------------------------------------------------------- -current_unix_time: - push eax esi - mov esi, current_bdfe_time - - ; Just a small observation: - ; The CMOS is a pretty bad source to get time from. One shouldn't rely on it, - ; since it messes up the time by tiny bits. Of course, this is all technical, - ; but one can look it up on the osdev wiki. What is better is to get the time - ; from CMOS during boot, then update system time using a more accurate timer. - ; I'll probably add that after the Summer of Code, so TODO! TODO! TODO!. - - ; Get time from CMOS. - ; Seconds. - mov al, 0x00 - out 0x70, al - in al, 0x71 - call bcd2bin - mov [esi + 0], al - - ; Minute. - mov al, 0x02 - out 0x70, al - in al, 0x71 - call bcd2bin - mov [esi + 1], al - - ; Hour. - mov al, 0x04 - out 0x70, al - in al, 0x71 - call bcd2bin - mov [esi + 2], al - - ; Get date. - - ; Day. - mov al, 0x7 - out 0x70, al - in al, 0x71 - call bcd2bin - mov [esi + 4], al - - ; Month. - mov al, 0x8 - out 0x70, al - in al, 0x71 - call bcd2bin - mov [esi + 5], al - - ; Year. - mov al, 0x9 - out 0x70, al - in al, 0x71 - call bcd2bin - add ax, 2000 ; CMOS only returns last two digits. - ; Note that everywhere in KolibriOS this is used. - ; This is hacky, since the RTC can be incorrectly set - ; to something before 2000. - mov [esi + 6], ax - - call bdfe_to_unix_time - pop esi eax - ret - -;--------------------------------------------------------------------- -; Convert time+date from BDFE to Unix time. -; Input: esi = pointer to BDFE time+date. -; edi = buffer to output Unix time. -;--------------------------------------------------------------------- -bdfe_to_unix_time: - push eax ebx ecx edx - mov dword[edi], 0x00000000 - - ; The minimum representable time is 1901-12-13. - cmp word[esi + 6], 1901 - jb .ret - jg .max - - cmp byte[esi + 5], 12 - jb .ret - - cmp byte[esi + 4], 13 - jbe .ret - jg .convert - - ; Check if it is more than the maximum representable time. - .max: - ; The maximum representable time is 2038-01-19. - cmp word[esi + 6], 2038 - jg .ret - jb .convert - - cmp byte[esi + 5], 1 - jg .ret - - cmp byte[esi + 4], 19 - jge .ret - - ; Convert the time. - .convert: - ; Get if current year is leap year in ECX. - xor ecx, ecx - mov ebx, 4 - xor edx, edx - - cmp word[esi + 6], 1970 - jb .negative - - movzx eax, word[esi + 6] ; Year. - cmp byte[esi + 5], 3 ; If the month is less than March, than that year doesn't matter. - jge @F - - test eax, 3 - ; Not a leap year. - jnz @F - - inc ecx - @@: - ; Number of leap years between two years = ((end date - 1)/4) - (1970/4) - dec eax - div ebx - sub eax, 1970/4 - - ; EAX is the number of leap years. - add eax, ecx - mov ecx, (60 * 60 * 24) ; Seconds in a day. - mul ecx - - ; Account for leap years, i.e., one day extra for each. - add [edi], eax - - ; Get total days in EAX. - movzx eax, byte[esi + 4] - dec eax - mul ecx - - ; Account for days. - add [edi], eax - - ; Account for month. - movzx eax, byte[esi + 5] - dec eax - mov eax, [cumulative_seconds_in_month + (eax * 4)] - add [edi], eax - - ; Account for year. - movzx eax, word[esi + 6] - sub eax, 1970 - mov ecx, (60 * 60 * 24) * 365 ; Seconds in a year. - mul ecx - add [edi], eax - - ; Seconds. - movzx eax, byte[esi + 0] - add [edi], eax - - ; Minutes. - movzx eax, byte[esi + 1] - mov ecx, 60 - mul ecx - add [edi], eax - - ; Hours. - movzx eax, byte[esi + 2] - mov ecx, (60 * 60) - mul ecx - add [edi], eax - - ; The time wanted is before the epoch; handle it here. - .negative: - ; TODO. - - .ret: - pop edx ecx ebx eax - ret - -; Recommended move to some kernel-wide alloc handling code. -macro KERNEL_ALLOC store, label -{ - call kernel_alloc - mov store, eax - test eax, eax - jz label -} - -macro KERNEL_FREE data, label -{ - cmp data, 0 - jz label - push data - call kernel_free -} - -struct EXTFS PARTITION - lock MUTEX - partition_flags dd ? - log_block_size dd ? - block_size dd ? - count_block_in_block dd ? - blocks_per_group dd ? - global_desc_table dd ? - root_inode dd ? ; Pointer to root inode in memory. - inode_size dd ? - count_pointer_in_block dd ? ; (block_size / 4) - count_pointer_in_block_square dd ? ; (block_size / 4)**2 - ext2_save_block dd ? ; Block for 1 global procedure. - ext2_temp_block dd ? ; Block for small procedures. - ext2_save_inode dd ? ; inode for global procedures. - ext2_temp_inode dd ? ; inode for small procedures. - groups_count dd ? - superblock rd 1024/4 -ends - -; EXT2 revisions. -EXT2_GOOD_OLD_REV = 0 - -; For fs_type. -FS_TYPE_UNDEFINED = 0 -FS_TYPE_EXT = 2 - -; Some set inodes. -EXT2_BAD_INO = 1 -EXT2_ROOT_INO = 2 -EXT2_ACL_IDX_INO = 3 -EXT2_ACL_DATA_INO = 4 -EXT2_BOOT_LOADER_INO = 5 -EXT2_UNDEL_DIR_INO = 6 - -; EXT2_SUPER_MAGIC. -EXT2_SUPER_MAGIC = 0xEF53 -EXT2_VALID_FS = 1 - -; Flags defining i_mode values. -EXT2_S_IFMT = 0xF000 ; Mask for file type. - -EXT2_S_IFREG = 0x8000 ; Regular file. -EXT2_S_IFDIR = 0x4000 ; Directory. - -EXT2_S_IRUSR = 0x0100 ; User read -EXT2_S_IWUSR = 0x0080 ; User write -EXT2_S_IXUSR = 0x0040 ; User execute -EXT2_S_IRGRP = 0x0020 ; Group read -EXT2_S_IWGRP = 0x0010 ; Group write -EXT2_S_IXGRP = 0x0008 ; Group execute -EXT2_S_IROTH = 0x0004 ; Others read -EXT2_S_IWOTH = 0x0002 ; Others write -EXT2_S_IXOTH = 0x0001 ; Others execute - -PERMISSIONS = EXT2_S_IRUSR or EXT2_S_IWUSR \ - or EXT2_S_IRGRP or EXT2_S_IWGRP \ - or EXT2_S_IROTH or EXT2_S_IWOTH - -; File type defining values in directory entry. -EXT2_FT_REG_FILE = 1 ; Regular file. -EXT2_FT_DIR = 2 ; Directory. - -; Flags used by KolibriOS. -FS_FT_HIDDEN = 2 -FS_FT_DIR = 0x10 ; Directory. - -; ext2 partition flags. -EXT2_RO = 0x01 - -FS_FT_ASCII = 0 ; Name in ASCII. -FS_FT_UNICODE = 1 ; Name in Unicode. - -EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ; Have file type in directory entry. -EXT4_FEATURE_INCOMPAT_EXTENTS = 0x0040 ; Extents. -EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x0200 ; Flexible block groups. - -EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER = 0x0001 ; Sparse Superblock -EXT2_FEATURE_RO_COMPAT_LARGE_FILE = 0x0002 ; Large file support (64-bit file size) - -; Implemented ext[2,3,4] features. -EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \ - or EXT4_FEATURE_INCOMPAT_EXTENTS \ - or EXT4_FEATURE_INCOMPAT_FLEX_BG - -; Implemented features which otherwise require "read-only" mount. -EXT2_FEATURE_RO_COMPAT_SUPP = EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER \ - or EXT2_FEATURE_RO_COMPAT_LARGE_FILE - -; ext4 features not support for write. -EXT4_FEATURE_INCOMPAT_W_NOT_SUPP = EXT4_FEATURE_INCOMPAT_EXTENTS \ - or EXT4_FEATURE_INCOMPAT_FLEX_BG - -; Flags specified in i_flags. -EXT2_EXTENTS_FL = 0x00080000 ; Extents. - -struct EXT2_INODE_STRUC - i_mode dw ? - i_uid dw ? - i_size dd ? - i_atime dd ? - i_ctime dd ? - i_mtime dd ? - i_dtime dd ? - i_gid dw ? - i_links_count dw ? - i_blocks dd ? - i_flags dd ? - i_osd1 dd ? - i_block rd 15 - i_generation dd ? - i_file_acl dd ? - i_dir_acl dd ? - i_faddr dd ? - i_osd2 dd ? ; 12 bytes. -ends - -struct EXT2_DIR_STRUC - inode dd ? - rec_len dw ? - name_len db ? - file_type db ? - name db ? ; 255 (max) bytes. -ends - -struct EXT2_BLOCK_GROUP_DESC - block_bitmap dd ? ; +0 - inode_bitmap dd ? ; +4 - inode_table dd ? ; +8 - free_blocks_count dw ? ; +12 - free_inodes_count dw ? ; +14 - used_dirs_count dw ? ; +16 - pad dw ? ; +18 - reserved rb 12 ; +20 -ends - -struct EXT2_SB_STRUC - inodes_count dd ? ; +0 - blocks_count dd ? ; +4 - r_block_count dd ? ; +8 - free_block_count dd ? ; +12 - free_inodes_count dd ? ; +16 - first_data_block dd ? ; +20 - log_block_size dd ? ; +24 - log_frag_size dd ? ; +28 - blocks_per_group dd ? ; +32 - frags_per_group dd ? ; +36 - inodes_per_group dd ? ; +40 - mtime dd ? ; +44 - wtime dd ? ; +48 - mnt_count dw ? ; +52 - max_mnt_count dw ? ; +54 - magic dw ? ; +56 - state dw ? ; +58 - errors dw ? ; +60 - minor_rev_level dw ? ; +62 - lastcheck dd ? ; +64 - check_intervals dd ? ; +68 - creator_os dd ? ; +72 - rev_level dd ? ; +76 - def_resuid dw ? ; +80 - def_resgid dw ? ; +82 - first_ino dd ? ; +84 - inode_size dw ? ; +88 - block_group_nr dw ? ; +90 - feature_compat dd ? ; +92 - feature_incompat dd ? ; +96 - feature_ro_compat dd ? ; +100 - uuid rb 16 ; +104 - volume_name rb 16 ; +120 - last_mounted rb 64 ; +136 - algo_bitmap dd ? ; +200 - prealloc_blocks db ? ; +204 - preallock_dir_blocks db ? ; +205 - reserved_gdt_blocks dw ? ; +206 - journal_uuid rb 16 ; +208 - journal_inum dd ? ; +224 - journal_dev dd ? ; +228 - last_orphan dd ? ; +232 - hash_seed rd 4 ; +236 - def_hash_version db ? ; +252 - reserved rb 3 ; +253 (reserved) - default_mount_options dd ? ; +256 - first_meta_bg dd ? ; +260 - mkfs_time dd ? ; +264 - jnl_blocks rd 17 ; +268 - blocks_count_hi dd ? ; +336 - r_blocks_count_hi dd ? ; +340 - free_blocks_count_hi dd ? ; +344 - min_extra_isize dw ? ; +348 - want_extra_isize dw ? ; +350 - flags dd ? ; +352 - raid_stride dw ? ; +356 - mmp_interval dw ? ; +358 - mmp_block dq ? ; +360 - raid_stripe_width dd ? ; +368 - log_groups_per_flex db ? ; +372 -ends - -; Header block extents. -struct EXT4_EXTENT_HEADER - eh_magic dw ? ; Magic value of 0xF30A, for ext4. - eh_entries dw ? ; Number of blocks covered by the extent. - eh_max dw ? ; Capacity of entries. - eh_depth dw ? ; Tree depth (if 0, extents in the array are not extent indexes) - eh_generation dd ? ; ??? -ends - -; Extent. -struct EXT4_EXTENT - ee_block dd ? ; First logical block extent covers. - ee_len dw ? ; Number of blocks covered by extent. - ee_start_hi dw ? ; Upper 16 bits of 48-bit address (unused in KOS) - ee_start_lo dd ? ; Lower 32 bits of 48-bit address. -ends - -; Index on-disk structure; pointer to block of extents/indexes. -struct EXT4_EXTENT_IDX - ei_block dd ? ; Covers logical blocks from here. - ei_leaf_lo dd ? ; Lower 32-bits of pointer to the physical block of the next level. - ei_leaf_hi dw ? ; Higher 16-bits (unused in KOS). - ei_unused dw ? ; Reserved. -ends \ No newline at end of file diff --git a/kernel/trunk/fs/ext2/inode.inc b/kernel/trunk/fs/ext2/inode.inc deleted file mode 100644 index ac2b6ea639..0000000000 --- a/kernel/trunk/fs/ext2/inode.inc +++ /dev/null @@ -1,1853 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Contains ext2 inode handling code. ;; -;; ;; -;; Copyright (C) KolibriOS team 2013-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;--------------------------------------------------------------------- -; Receives block number from extent-based inode. -; Input: ecx = number of block in inode -; esi = address of extent header -; ebp = pointer to EXTFS -; Output: ecx = address of next block, if successful -; eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext4_block_recursive_search: - cmp word [esi + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC - jne .fail - - movzx ebx, [esi + EXT4_EXTENT_HEADER.eh_entries] - add esi, sizeof.EXT4_EXTENT_HEADER - cmp word [esi - sizeof.EXT4_EXTENT_HEADER + EXT4_EXTENT_HEADER.eh_depth], 0 - je .leaf_block ;листовой ли это блок? - - ;не листовой блок, а индексный ; eax - ext4_extent_idx - test ebx, ebx - jz .fail ;пустой индексный блок -> ошибка - - ;цикл по индексам экстентов - @@: - cmp ebx, 1 ;у индексов не хранится длина, - je .end_search_index ;поэтому, если остался последний - то это нужный - - cmp ecx, [esi + EXT4_EXTENT_IDX.ei_block] - jb .fail - - cmp ecx, [esi + sizeof.EXT4_EXTENT_IDX + EXT4_EXTENT_IDX.ei_block] ;блок слeдующего индекса - jb .end_search_index ;следующий дальше - значит текущий, то что нам нужен - - add esi, sizeof.EXT4_EXTENT_IDX - dec ebx - jmp @B - - .end_search_index: - ;ebp указывает на нужный extent_idx, считываем следующий блок - mov ebx, [ebp + EXTFS.ext2_temp_block] - mov eax, [esi + EXT4_EXTENT_IDX.ei_leaf_lo] - call ext2_block_read - test eax, eax - jnz .fail - mov esi, ebx - jmp ext4_block_recursive_search ;рекурсивно прыгаем в начало - - .leaf_block: ;листовой блок esi - ext4_extent - ;цикл по экстентам - @@: - test ebx, ebx - jz .fail ;ни один узел не подошел - ошибка - - mov edx, [esi + EXT4_EXTENT.ee_block] - cmp ecx, edx - jb .fail ;если меньше, значит он был в предыдущих блоках -> ошибка - - movzx edi, [esi + EXT4_EXTENT.ee_len] - add edx, edi - cmp ecx, edx - jb .end_search_extent ;нашли нужный блок - - add esi, sizeof.EXT4_EXTENT - dec ebx - jmp @B - - .end_search_extent: - mov edx, [esi + EXT4_EXTENT.ee_start_lo] - sub ecx, [esi + EXT4_EXTENT.ee_block] ;разница в ext4 блоках - add ecx, edx - xor eax, eax - ret - - .fail: - mov eax, ERROR_FS_FAIL - ret - -;--------------------------------------------------------------------- -; Frees triply indirect block. -; Input: eax = triply indirect block. -; [ebp + EXTFS.ext2_save_inode] = the inode. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_inode_free_triply_indirect: - push ebx edx - - test eax, eax - jz .success - push eax - ; Read the triple indirect block. - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - pop eax - jnz .fail - - ; Free the triple indirect block. - call ext2_block_free - test eax, eax - jnz .fail - - mov edx, ebx - add edx, [ebp + EXTFS.block_size] - - @@: - mov eax, [ebx] - test eax, eax - jz .success - - call ext2_inode_free_doubly_indirect - cmp eax, 1 - je .success - cmp eax, 0xFFFFFFFF - je .fail - - add ebx, 4 - cmp ebx, edx - jb @B - - .success: - xor eax, eax - .ret: - pop edx ebx - ret - - .fail: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Frees double indirect block. -; Input: eax = double indirect block. -; [ebp + EXTFS.ext2_save_inode] = the inode. -; Output: eax = error code, 1 implies finished, ~0 implies error -;--------------------------------------------------------------------- -ext2_inode_free_doubly_indirect: - push ebx edx - - test eax, eax - jz .complete - push eax - ; Read the double indirect block. - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - pop eax - jnz .fail - - call ext2_block_free - test eax, eax - jnz .fail - - mov edx, ebx - add edx, [ebp + EXTFS.block_size] - - @@: - mov eax, [ebx] - test eax, eax - jz .complete - - call ext2_block_free - test eax, eax - jnz .fail - - add ebx, 4 - cmp ebx, edx - jb @B - - .success: - xor eax, eax - .ret: - pop edx ebx - ret - - .complete: - xor eax, eax - inc eax - jmp .ret - - .fail: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Frees all indirect blocks. -; Input: ebp = pointer to EXTFS. -; [ebp + EXTFS.ext2_save_inode] = the inode. -; Output: eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_inode_free_indirect_blocks: - push edi - - mov edi, [ebp + EXTFS.ext2_save_inode] - - ; Free indirect block. - mov eax, [edi + EXT2_INODE_STRUC.i_block + 12*4] - test eax, eax - jz .success - - call ext2_block_free - test eax, eax - jnz .fail - - mov eax, [edi + EXT2_INODE_STRUC.i_block + 13*4] - call ext2_inode_free_doubly_indirect - cmp eax, 1 - je .success - cmp eax, 0xFFFFFFFF - je .fail - - mov eax, [edi + EXT2_INODE_STRUC.i_block + 14*4] - call ext2_inode_free_triply_indirect - test eax, eax - jnz .fail - - .success: - xor eax, eax - .ret: - pop edi - ret - - .fail: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Allocates block for inode. -; Input: esi = address of inode -; ebp = pointer to EXTFS. -; Output: eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_inode_calloc_block: - push ecx - - ; TODO: fix to have correct preference. - mov eax, EXT2_ROOT_INO - call ext2_block_calloc - test eax, eax - jnz .fail - - mov ecx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.log_block_size] - mov eax, 2 - shl eax, cl - add [esi + EXT2_INODE_STRUC.i_blocks], eax - - .success: - xor eax, eax - .ret: - pop ecx - ret - - .fail: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Sets block ID for indirect-addressing inode. -; Input: ecx = index of block in inode -; edi = block ID to set to -; esi = address of inode -; ebp = pointer to EXTFS. -; Output: eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_inode_set_block: - push ebx ecx edx - - ; 0 to 11: direct blocks. - cmp ecx, 12 - jb .direct_block - - ; Indirect blocks - sub ecx, 12 - cmp ecx, [ebp + EXTFS.count_pointer_in_block] - jb .indirect_block - - ; Double indirect blocks. - sub ecx, [ebp + EXTFS.count_pointer_in_block] - cmp ecx, [ebp + EXTFS.count_pointer_in_block_square] - jb .double_indirect_block - - ; Triple indirect blocks. - sub ecx, [ebp + EXTFS.count_pointer_in_block_square] - - ; Get triply-indirect block in temp_block. - mov eax, [esi + EXT2_INODE_STRUC.i_block + 14*4] - test eax, eax - jnz @F - - call ext2_inode_calloc_block - test eax, eax - jnz .fail_alloc - - mov [esi + EXT2_INODE_STRUC.i_block + 14*4], ebx - mov eax, ebx - - @@: - push eax - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .fail_alloc_4 - - ; Get index in triply-indirect block. - xor edx, edx - mov eax, ecx - div [ebp + EXTFS.count_pointer_in_block_square] - - ; eax: index in triply-indirect block, edx: index in doubly-indirect block. - lea ecx, [ebx + eax*4] - mov eax, [ebx + eax*4] - test eax, eax - jnz @F - - call ext2_inode_calloc_block - test eax, eax - jnz .fail_alloc_4 - - mov [ecx], ebx - - mov eax, [esp] - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_write - test eax, eax - jnz .fail_alloc_4 - - mov eax, [ecx] - @@: - mov [esp], eax - call ext2_block_read - test eax, eax - jnz .fail_alloc_4 - - mov eax, edx - jmp @F - - .double_indirect_block: - ; Get doubly-indirect block. - mov eax, [esi + EXT2_INODE_STRUC.i_block + 13*4] - test eax, eax - jnz .double_indirect_present - - call ext2_inode_calloc_block - test eax, eax - jnz .fail_alloc - - mov [esi + EXT2_INODE_STRUC.i_block + 13*4], ebx - mov eax, ebx - - .double_indirect_present: - ; Save block we're at. - push eax - - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .fail_alloc_4 - - mov eax, ecx - @@: - xor edx, edx - div [ebp + EXTFS.count_pointer_in_block] - - ; eax: index in doubly-indirect block, edx: index in indirect block. - lea ecx, [ebx + edx*4] - push ecx - - lea ecx, [ebx + eax*4] - cmp dword[ecx], 0 - jne @F - - call ext2_inode_calloc_block - test eax, eax - jnz .fail_alloc_8 - - mov [ecx], ebx - - mov eax, [esp + 4] - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_write - test eax, eax - jnz .fail_alloc_8 - - @@: - mov eax, [ecx] - push eax - call ext2_block_read - test eax, eax - jnz .fail_alloc_12 - - pop eax - pop ecx - mov [ecx], edi - call ext2_block_write - - add esp, 4 - jmp .return - - .indirect_block: - ; Get index of indirect block. - mov eax, [esi + EXT2_INODE_STRUC.i_block + 12*4] - test eax, eax - jnz @F - - call ext2_inode_calloc_block - test eax, eax - jnz .fail_alloc - - mov [esi + EXT2_INODE_STRUC.i_block + 12*4], ebx - mov eax, ebx - - @@: - push eax - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .fail_alloc_4 - - ; Get the block ID. - mov [ebx + ecx*4], edi - pop eax - call ext2_block_write - jmp .return - - .direct_block: - mov [esi + EXT2_INODE_STRUC.i_block + ecx*4], edi - xor eax, eax - - .return: - pop edx ecx ebx - ret - - .fail_alloc: - xor eax, eax - not eax - jmp .return - - .fail_alloc_12: - add esp, 4 - .fail_alloc_8: - add esp, 4 - .fail_alloc_4: - add esp, 4 - jmp .fail_alloc - -;--------------------------------------------------------------------- -; Receives block ID from indirect-addressing inode. -; Input: ecx = index of block in inode -; esi = address of inode -; ebp = pointer to EXTFS -; Output: ecx = block ID, if successful -; eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_inode_get_block: - ; If inode is extent-based, use ext4_block_recursive_search. - test [esi + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL - jz @F - - pushad - - ; Get extent header in EBP. - add esi, EXT2_INODE_STRUC.i_block - call ext4_block_recursive_search - mov PUSHAD_ECX, ecx - mov PUSHAD_EAX, eax - - popad - ret - - @@: - ; 0 to 11: direct blocks. - cmp ecx, 12 - jb .get_direct_block - - ; Indirect blocks - sub ecx, 12 - cmp ecx, [ebp + EXTFS.count_pointer_in_block] - jb .get_indirect_block - - ; Double indirect blocks. - sub ecx, [ebp + EXTFS.count_pointer_in_block] - cmp ecx, [ebp + EXTFS.count_pointer_in_block_square] - jb .get_double_indirect_block - - ; Triple indirect blocks. - sub ecx, [ebp + EXTFS.count_pointer_in_block_square] - push edx ebx - - ; Get triply-indirect block in temp_block. - mov eax, [esi + EXT2_INODE_STRUC.i_block + 14*4] - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .fail - - ; Get index in triply-indirect block. - xor edx, edx - mov eax, ecx - div [ebp + EXTFS.count_pointer_in_block_square] - - ; eax: index in triply-indirect block, edx: index in doubly-indirect block. - mov eax, [ebx + eax*4] - test eax, eax - jz .fail_triple_indirect_block - - call ext2_block_read - test eax, eax - jnz .fail - - mov eax, edx - jmp @F - - .get_double_indirect_block: - push edx ebx - - ; Get doubly-indirect block. - mov eax, [esi + EXT2_INODE_STRUC.i_block + 13*4] - test eax, eax - jz .fail_double_indirect_block - - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .fail - - mov eax, ecx - @@: - xor edx, edx - div [ebp + EXTFS.count_pointer_in_block] - - ; eax: index in doubly-indirect block, edx: index in indirect block. - mov eax, [ebx + eax*4] - test eax, eax - jz .fail_double_indirect_block - - call ext2_block_read - test eax, eax - jnz .fail - - mov ecx, [ebx + edx*4] - .fail: - pop ebx edx - - ret - - .get_indirect_block: - push ebx - - ; Get index of indirect block. - mov eax, [esi + EXT2_INODE_STRUC.i_block + 12*4] - test eax, eax - jz .fail_indirect_block - - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz @F - - mov ecx, [ebx + ecx*4] - @@: - pop ebx - - ret - - .get_direct_block: - mov ecx, [esi + EXT2_INODE_STRUC.i_block + ecx*4] - xor eax, eax - - ret - - .fail_indirect_block: - pop ebx - - .fail_triple_indirect_block: - xor eax, eax - xor ecx, ecx - ret - - .fail_double_indirect_block: - pop ebx edx - jmp .fail_triple_indirect_block - -;--------------------------------------------------------------------- -; Get block containing inode. -; Input: eax = inode number. -; ebp = pointer to EXTFS. -; Output: ebx = block (hard disk) containing inode. -; edx = index inside block. -; eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_read_block_of_inode: - pushad - - dec eax - xor edx, edx - - ; EAX = block group. - div [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group] - - push edx ; Index in group. - - mov edx, 32 - mul edx ; Get index of descriptor in global_desc_table. - - ; eax: inode group offset relative to global descriptor table start - ; Find the block this block descriptor is in. - div [ebp + EXTFS.block_size] - add eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block] - inc eax - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .return - - add ebx, edx ; edx: local index of descriptor inside block - mov eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table] ; Block number of inode table - in ext2 terms. - mov ecx, [ebp + EXTFS.log_block_size] - shl eax, cl - - ; eax: points to inode table on HDD. - mov esi, eax - - ; Add local address of inode. - pop eax - mov ecx, [ebp + EXTFS.inode_size] - mul ecx ; (index * inode_size) - - mov ebp, 512 - div ebp ; Divide by hard disk block size. - - add eax, esi ; Found block to read. - mov ebx, eax ; Get it inside ebx. - - xor eax, eax - .return: - mov PUSHAD_EAX, eax - mov PUSHAD_EBX, ebx - mov PUSHAD_EDX, edx - - popad - ret - -;--------------------------------------------------------------------- -; Sets content of inode by number. -; Input: eax = inode number. -; ebx = address from where to write inode content. -; ebp = pointer to EXTFS. -; Output: eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_inode_write: - push edx edi esi ecx ebx - mov esi, ebx - - ; Ext2 actually stores time of modification of inode in ctime. - lea edi, [ebx + EXT2_INODE_STRUC.i_ctime] - call current_unix_time - - ; Get block where inode is situated. - call ext2_read_block_of_inode - test eax, eax - jnz .error - - mov eax, ebx ; Get block into EAX. - mov ebx, [ebp + EXTFS.ext2_temp_block] - - mov ecx, eax ; Save block. - call fs_read32_sys - test eax, eax - jz @F - - .error: - mov eax, ERROR_DEVICE - jmp .return - - @@: - mov eax, ecx - mov ecx, [ebp + EXTFS.inode_size] - mov edi, edx ; The index into the block. - add edi, ebx - rep movsb - - ; Write the block. - call fs_write32_sys - - .return: - pop ebx ecx esi edi edx - ret - -;--------------------------------------------------------------------- -; Get content of inode by number. -; Input: eax = inode number. -; ebx = address where to store inode content. -; ebp = pointer to EXTFS. -; Output: eax = error code (0 implies no error) -;--------------------------------------------------------------------- -ext2_inode_read: - push edx edi esi ecx ebx - mov edi, ebx - - ; Get block where inode is situated. - call ext2_read_block_of_inode - test eax, eax - jnz .error - - mov eax, ebx ; Get block into EAX. - mov ebx, [ebp + EXTFS.ext2_temp_block] - call fs_read32_sys - test eax, eax - jz @F - - .error: - mov eax, ERROR_DEVICE - jmp .return - - @@: - mov ecx, [ebp + EXTFS.inode_size] - mov esi, edx ; The index into the inode. - add esi, ebx - rep movsb - - xor eax, eax - .return: - pop ebx ecx esi edi edx - ret - -;--------------------------------------------------------------------- -; Seek inode from the path. -; Input: esi + [esp + 4] = name. -; ebp = pointer to EXTFS. -; Output: eax = error code (0 implies no error) -; esi = inode number. -; dl = first byte of file/folder name. -; [ext2_data.ext2_save_inode] stores the inode. -;--------------------------------------------------------------------- -ext2_inode_find: - mov edx, [ebp + EXTFS.root_inode] - - ; Check for empty root. - cmp [edx + EXT2_INODE_STRUC.i_blocks], 0 - je .error_empty_root - - ; Check for root. - cmp byte[esi], 0 - jne .next_path_part - - push edi ecx - mov esi, [ebp + EXTFS.root_inode] - mov edi, [ebp + EXTFS.ext2_save_inode] - mov ecx, [ebp + EXTFS.inode_size] - rep movsb - pop ecx edi - - xor eax, eax - xor dl, dl - mov esi, EXT2_ROOT_INO - ret 4 - - .next_path_part: - push [edx + EXT2_INODE_STRUC.i_blocks] - xor ecx, ecx - - .folder_block_cycle: - push ecx - xchg esi, edx - call ext2_inode_get_block - xchg esi, edx - test eax, eax - jnz .error_get_inode_block - - mov eax, ecx - mov ebx, [ebp + EXTFS.ext2_save_block] ; Get directory records from directory. - call ext2_block_read - test eax, eax - jnz .error_get_block - - push esi - push edx - call ext2_block_find_parent - pop edx - pop edi ecx - - cmp edi, esi ; Did something match? - je .next_folder_block ; No, move to next block. - - cmp byte [esi], 0 ; Reached the "end" of path successfully. - jnz @F - cmp dword[esp + 8], 0 - je .get_inode_ret - mov esi, [esp + 8] - mov dword[esp + 8], 0 - - @@: - mov eax, [ebx + EXT2_DIR_STRUC.inode] - mov ebx, [ebp + EXTFS.ext2_save_inode] - call ext2_inode_read - test eax, eax - jnz .error_get_inode - - movzx eax, [ebx + EXT2_INODE_STRUC.i_mode] - and eax, EXT2_S_IFMT ; Get the mask. - cmp eax, EXT2_S_IFDIR - jne .not_found ; Matched till part, but directory entry we got doesn't point to folder. - - pop ecx ; Stack top contains number of blocks. - mov edx, ebx - jmp .next_path_part - - .next_folder_block: - ; Next block in current folder. - pop eax ; Get blocks counter. - sub eax, [ebp + EXTFS.count_block_in_block] - jle .not_found - - push eax - inc ecx - jmp .folder_block_cycle - - .not_found: - mov eax, ERROR_FILE_NOT_FOUND - ret 4 - - .get_inode_ret: - pop ecx ; Stack top contains number of blocks. - - mov dl, [ebx + EXT2_DIR_STRUC.name] ; First character of file-name. - mov eax, [ebx + EXT2_DIR_STRUC.inode] - mov ebx, [ebp + EXTFS.ext2_save_inode] - mov esi, eax - - ; If we can't get the inode, eax contains the error. - call ext2_inode_read - ret 4 - - .error_get_inode_block: - .error_get_block: - pop ecx - .error_get_inode: - pop ebx - .error_empty_root: - mov eax, ERROR_FS_FAIL - ret 4 - -;--------------------------------------------------------------------- -; Seeks parent inode from path. -; Input: esi = path. -; ebp = pointer to EXTFS. -; Output: eax = error code. -; esi = inode. -; edi = pointer to file name. -;--------------------------------------------------------------------- -ext2_inode_find_parent: - push esi - xor edi, edi - - .loop: - cmp byte[esi], '/' - jne @F - - mov edi, esi - inc esi - jmp .loop - - @@: - inc esi - cmp byte[esi - 1], 0 - jne .loop - - ; If it was just a filename (without any additional directories), - ; use the last byte as "parent path". - cmp edi, 0 - jne @F - - pop edi - dec esi - jmp .get_inode - - ; It had some additional directories, so handle it that way. - @@: - mov byte[edi], 0 - inc edi - pop esi - - .get_inode: - push ebx edx - stdcall ext2_inode_find, 0 - pop edx ebx - - .return: - ret - -;--------------------------------------------------------------------- -; Link an inode. -; Input: eax = inode on which to link. -; ebx = inode to link. -; dl = file type. -; esi = name. -; ebp = pointer to EXTFS. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_inode_link: - push eax - push esi edi ebx ecx edx - - ; Get string length, and then directory entry structure size. - call strlen - add ecx, 8 - - push esi ebx ecx - - xor ecx, ecx - mov esi, [ebp + EXTFS.ext2_temp_inode] - mov ebx, esi - - call ext2_inode_read - test eax, eax - jnz .error_inode_read - - ; Get the maximum addressible i_block index by (i_blocks/(2 << s_log_block_size)). - ; Note that i_blocks contains number of reserved 512B blocks, which is why we've to - ; find out the ext2 blocks. - mov eax, 2 - mov ecx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.log_block_size] - shl eax, cl - mov ecx, eax - - mov eax, [esi + EXT2_INODE_STRUC.i_blocks] - xor edx, edx - - div ecx - - ; EAX is the maximum index inside i_block we can go. - push eax - push dword 0 - - ; ECX contains the "block inside i_block" index. - xor ecx, ecx - @@: - call ext2_inode_get_block - test eax, eax - jnz .error_get_inode_block - test ecx, ecx - jz .alloc_block ; We've got no block here, so allocate one. - - push ecx ; Save block number. - - mov eax, ecx - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .error_block_read - - ; Try to find free space in current block. - mov ecx, [esp + 8] - call ext2_block_find_fspace - test eax, eax - jz .found - - cmp eax, 0x00000001 - jne .next_iter - - ; This block wasn't linking to the next block, so fix that, and use the next one. - ; Write the block. - pop eax - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_write - test eax, eax - jnz .error_get_inode_block - - inc dword [esp] - mov ecx, [esp] - call ext2_inode_get_block - test eax, eax - jnz .error_get_inode_block - - test ecx, ecx - jz .alloc_block - - ; If there was a block there, prepare it for our use! - push ecx - jmp .prepare_block - - .next_iter: - add esp, 4 - - inc dword [esp] - mov ecx, [esp] - cmp ecx, [esp + 4] - jbe @B - - .alloc_block: - mov eax, [esp + 12] ; Get inode ID of what we're linking. - call ext2_block_calloc - test eax, eax - jnz .error_get_inode_block - - mov ecx, [esp] ; Get the index of it inside the inode. - mov edi, ebx ; And what to set to. - call ext2_inode_set_block - test eax, eax - jnz .error_get_inode_block - - ; Update i_size. - mov eax, [ebp + EXTFS.block_size] - add [esi + EXT2_INODE_STRUC.i_size], eax - - ; Update i_blocks. - mov ecx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.log_block_size] - mov eax, 2 - shl eax, cl - add [esi + EXT2_INODE_STRUC.i_blocks], eax - - ; Write the inode. - mov eax, [esp + 40] - mov ebx, esi - call ext2_inode_write - test eax, eax - jnz .error_get_inode_block - - push edi ; Save the block we just allocated. - - ; If we've allocated/using-old-block outside of loop, prepare it. - .prepare_block: - mov eax, [esp] - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .error_block_read - - mov edi, ebx - mov eax, [ebp + EXTFS.block_size] - mov [edi + EXT2_DIR_STRUC.rec_len], ax - - .found: - pop edx - add esp, 8 - pop ecx ebx esi - - push ebx - mov [edi], ebx ; Save inode. - - mov eax, [esp + 4] ; Get EDX off the stack -- contains the file_type. - cmp [ebp + EXTFS.superblock + EXT2_SB_STRUC.rev_level], EXT2_GOOD_OLD_REV - je .name - - ; Set the file-type. - mov [edi + EXT2_DIR_STRUC.file_type], al - - .name: - ; Save name. - sub ecx, 8 - mov [edi + EXT2_DIR_STRUC.name_len], cl - add edi, 8 - rep movsb - - ; Write block. - mov eax, edx - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_write - test eax, eax - jnz .error_block_write - - mov eax, [esp] - mov ebx, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_read - test eax, eax - jnz .error_block_write - - pop eax - inc [ebx + EXT2_INODE_STRUC.i_links_count] - call ext2_inode_write - test eax, eax - jnz .error - - xor eax, eax - .ret: - pop edx ecx ebx edi esi - add esp, 4 - ret - - .error_block_read: - add esp, 4 - .error_get_inode_block: - add esp, 8 - .error_inode_read: - add esp, 8 - .error_block_write: - add esp, 4 - .error: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Unlink an inode. -; Input: eax = inode from which to unlink. -; ebx = inode to unlink. -; ebp = pointer to EXTFS. -; Output: eax = number of links to inode, after unlinking (0xFFFFFFFF implies error) -;--------------------------------------------------------------------- -ext2_inode_unlink: - push ebx ecx edx esi edi - - push ebx - mov ebx, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_read - - test eax, eax - jnz .fail_get_inode - - ; The index into the inode block data. - push dword 0 - mov esi, [ebp + EXTFS.ext2_temp_inode] - - .loop: - mov ecx, [esp] - call ext2_inode_get_block - - test eax, eax - jnz .fail_loop - test ecx, ecx - jz .fail_loop - - mov eax, ecx - mov edi, eax - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .fail_loop - - ; edi -> block. - .first_dir_entry: - mov eax, [esp + 4] - cmp [ebx], eax - jne @F - - mov dword[ebx], 0 ; inode. - mov word[ebx + 6], 0 ; name_len + file_type. - jmp .write_block - - @@: - mov edx, ebx - add edx, [ebp + EXTFS.block_size] - push edx - - mov edx, ebx - movzx ecx, [ebx + EXT2_DIR_STRUC.rec_len] - add ebx, ecx - - .dir_entry: - cmp [ebx], eax - jne @F - - mov cx, [ebx + EXT2_DIR_STRUC.rec_len] - add [edx + EXT2_DIR_STRUC.rec_len], cx - add esp, 4 - jmp .write_block - - @@: - mov edx, ebx - movzx ecx, [ebx + EXT2_DIR_STRUC.rec_len] - - ; If it's a zero length entry, error. - test ecx, ecx - jz .fail_inode - - add ebx, ecx - - cmp ebx, [esp] - jb .dir_entry - - add esp, 4 - inc dword[esp] - jmp .loop - - .write_block: - mov eax, edi - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_write - test eax, eax - jnz .fail_loop - - add esp, 4 - mov ebx, [ebp + EXTFS.ext2_temp_inode] - mov eax, [esp] - call ext2_inode_read - test eax, eax - jnz .fail_get_inode - - dec word[ebx + EXT2_INODE_STRUC.i_links_count] - movzx eax, word[ebx + EXT2_INODE_STRUC.i_links_count] - push eax - - mov eax, [esp + 4] - call ext2_inode_write - test eax, eax - jnz .fail_loop - - pop eax - add esp, 4 - .return: - pop edi esi edx ecx ebx - ret - - .fail_inode: - add esp, 4 - - .fail_loop: - add esp, 4 - - .fail_get_inode: - add esp, 4 - - .fail: - xor eax, eax - not eax - jmp .return - -;--------------------------------------------------------------------- -; Checks if a directory is empty. -; Input: ebx = inode to check. -; ebp = pointer to EXTFS. -; [EXTFS.ext2_save_inode] = points to saved inode. -; Output: eax = 0 signifies empty directory. -;--------------------------------------------------------------------- -ext2_dir_empty: - push ebx ecx edx - - ; The index into the inode block data. - push dword 0 - mov esi, [ebp + EXTFS.ext2_save_inode] - - .loop: - mov ecx, [esp] - call ext2_inode_get_block - - ; Treat a failure as not-empty. - test eax, eax - jnz .not_empty - test ecx, ecx - jz .empty - - mov eax, ecx - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz .not_empty - - mov edx, ebx - add edx, [ebp + EXTFS.block_size] - - movzx ecx, [ebx + EXT2_DIR_STRUC.rec_len] - add ebx, ecx - - .dir_entry: - ; Process entry. - cmp byte[ebx + EXT2_DIR_STRUC.name_len], 1 - jne @F - - cmp byte[ebx + EXT2_DIR_STRUC.name], '.' - jne .not_empty - - @@: - cmp byte[ebx + EXT2_DIR_STRUC.name_len], 2 - jne .not_empty - - cmp word[ebx + EXT2_DIR_STRUC.name], '..' - jne .not_empty - - @@: - movzx ecx, [ebx + EXT2_DIR_STRUC.rec_len] - add ebx, ecx - - cmp ebx, edx - jb .dir_entry - - inc dword[esp] - jmp .loop - - .empty: - xor eax, eax - .return: - add esp, 4 - pop edx ecx ebx - ret - - .not_empty: - xor eax, eax - not eax - jmp .return - -;--------------------------------------------------------------------- -; Gets the block group's inode bitmap. -; Input: eax = block group. -; Output: eax = if zero, error; else, points to block group descriptor. -; ebx = inode bitmap's block (hard disk). -;--------------------------------------------------------------------- -ext2_bg_read_inode_bitmap: - push ecx - - call ext2_bg_read_desc - test eax, eax - jz .fail - - mov ebx, [eax + EXT2_BLOCK_GROUP_DESC.inode_bitmap] ; Block number of inode bitmap - in ext2 terms. - - .return: - pop ecx - ret - - .fail: - xor eax, eax - jmp .return - -;--------------------------------------------------------------------- -; Allocates a inode. -; Input: eax = inode ID for "preference". -; ebp = pointer to EXTFS. -; Output: Inode marked as set in inode group. -; eax = error code. -; ebx = inode ID. -;--------------------------------------------------------------------- -ext2_inode_alloc: - push [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_count] - push EXT2_BLOCK_GROUP_DESC.free_inodes_count - push [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group] - - lea ebx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.free_inodes_count] - push ebx - - push ext2_bg_read_inode_bitmap - - call ext2_resource_alloc - - ; Inode table starts with 1. - inc ebx - - ret - -;--------------------------------------------------------------------- -; Frees a inode. -; Input: eax = inode ID. -; ebp = pointer to EXTFS. -; Output: inode marked as free in block group. -; eax = error code. -;--------------------------------------------------------------------- -ext2_inode_free: - push edi ecx - - ; Inode table starts with 1. - dec eax - - mov edi, ext2_bg_read_inode_bitmap - xor ecx, ecx - inc cl - call ext2_resource_free - - pop ecx edi - ret - -;--------------------------------------------------------------------- -; Blanks a particular entry in an inode. -; Input: eax = index into block. -; edx = inode. -; ebp = pointer to EXTFS. -; [ebp + EXTFS.ext2_temp_inode] = the inode. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_inode_blank_entry: - push ebx ecx edx edi esi - - mov edi, eax - - mov ecx, eax - mov esi, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_get_block - test eax, eax - jnz .error - - test ecx, ecx - jz .allocate - - mov edx, ecx - mov ecx, [ebp + EXTFS.block_size] - mov edi, [ebp + EXTFS.ext2_temp_block] - xor eax, eax - rep stosb - - mov eax, edx - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_write - test eax, eax - jnz .error - - jmp .success - - ; Need to allocate a block. - .allocate: - mov eax, edx - call ext2_block_calloc - test eax, eax - jnz .error - - mov ecx, edi - mov edi, ebx - mov esi, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_set_block - test eax, eax - jnz .error - - mov ecx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.log_block_size] - mov eax, 2 - shl eax, cl - add [esi + EXT2_INODE_STRUC.i_blocks], eax - - .success: - xor eax, eax - - .ret: - pop esi edi edx ecx ebx - ret - - .error: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Frees a particular entry in an inode. -; Input: eax = index into block. -; ebp = pointer to EXTFS. -; [ebp + EXTFS.ext2_temp_inode] = the inode. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_inode_free_entry: - push ebx ecx edi esi - - mov edi, eax - - mov ecx, eax - mov esi, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_get_block - test eax, eax - jnz .error - - test ecx, ecx - jz .success - - mov eax, ecx - call ext2_block_free - test eax, eax - jnz .error - - mov ecx, edi - xor edi, edi - mov esi, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_set_block - - mov ecx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.log_block_size] - mov eax, 2 - shl eax, cl - sub [esi + EXT2_INODE_STRUC.i_blocks], eax - - .success: - xor eax, eax - - .ret: - pop esi edi ecx ebx - ret - - .error: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Reads a particular entry from an inode. -; Input: eax = index into block. -; ebp = pointer to EXTFS. -; [ebp + EXTFS.ext2_temp_inode] = the inode. -; Output: eax = error code. -; [ebp + EXTFS.ext2_save_block] = the read block. -;--------------------------------------------------------------------- -ext2_inode_read_entry: - push ebx ecx edx esi - - mov ecx, eax - mov esi, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_get_block - test eax, eax - jnz .error - - test ecx, ecx - jz .error - - mov eax, ecx - mov ebx, [ebp + EXTFS.ext2_save_block] - call ext2_block_read - test eax, eax - jnz .error - - .ret: - pop esi edx ecx ebx - ret - - .error: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Writes a particular entry from an inode. -; Input: eax = index into block. -; ebp = pointer to EXTFS. -; [ebp + EXTFS.ext2_temp_inode] = the inode. -; [ebp + EXTFS.ext2_save_block] = the block to write. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_inode_write_entry: - push ebx ecx edx esi - - mov ecx, eax - mov esi, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_get_block - test eax, eax - jnz .error - - test ecx, ecx - jz .error - - mov eax, ecx - mov ebx, [ebp + EXTFS.ext2_save_block] - call ext2_block_write - test eax, eax - jnz .error - - .ret: - pop esi edx ecx ebx - ret - - .error: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Extends inode to said size. -; Input: eax = inode ID. -; ecx = size to extend to. -; ebp = pointer to EXTFS. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_inode_extend: - push ebx ecx edx esi edi - - ; Save the inode. - push eax - - ; Read the inode. - mov ebx, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_read - test eax, eax - jnz .error - - mov eax, [ebx + EXT2_INODE_STRUC.i_size] - cmp eax, ecx - jge .success - - ; Save the size of the inode. - push eax - - ; ECX contains the size we've to write. - sub ecx, eax - xor edx, edx - div [ebp + EXTFS.block_size] - - test edx, edx - jz .start_aligned - - ; Start isn't aligned, so deal with the non-aligned bytes. - mov esi, [ebp + EXTFS.block_size] - sub esi, edx - - cmp esi, ecx - jbe @F - - ; If the size to entend to fits in current block, limit to that. - mov esi, ecx - - @@: - ; Clear ESI bytes, in EAX indexed block. - push eax - call ext2_inode_read_entry - test eax, eax - pop eax - jnz .error_inode_size - - push eax ecx - - xor eax, eax - mov ecx, esi - mov edi, ebx - add edi, edx - - rep stosb - - pop ecx eax - - ; Write the block. - call ext2_inode_write_entry - test eax, eax - jnz .error_inode_size - - add [esp], esi - sub ecx, esi - jz .write_inode - - .start_aligned: - cmp ecx, [ebp + EXTFS.block_size] - jb @F - - mov eax, [esp] - xor edx, edx - div [ebp + EXTFS.block_size] - - mov edx, [esp + 4] - call ext2_inode_blank_entry - - test eax, eax - jnz .error_inode_size - - mov eax, [ebp + EXTFS.block_size] - sub ecx, eax - add [esp], eax - jmp .start_aligned - - ; Handle the remaining bytes. - @@: - test ecx, ecx - jz .write_inode - - mov eax, [esp] - xor edx, edx - div [ebp + EXTFS.block_size] - - mov edx, [esp + 4] - call ext2_inode_blank_entry - - test eax, eax - jnz .error_inode_size - add [esp], ecx - - .write_inode: - mov ebx, [ebp + EXTFS.ext2_temp_inode] - pop eax - mov [ebx + EXT2_INODE_STRUC.i_size], eax - mov eax, [esp] - call ext2_inode_write - - test eax, eax - jnz .error - - .success: - xor eax, eax - - .ret: - add esp, 4 - - pop edi esi edx ecx ebx - ret - - .error_inode_size: - mov ebx, [ebp + EXTFS.ext2_temp_inode] - pop eax - mov [ebx + EXT2_INODE_STRUC.i_size], eax - mov eax, [esp] - call ext2_inode_write - - .error: - xor eax, eax - not eax - jmp .ret - -;--------------------------------------------------------------------- -; Truncates inode to said size. -; Input: eax = inode ID. -; ecx = size to truncate to. -; ebp = pointer to EXTFS. -; Output: eax = error code. -;--------------------------------------------------------------------- -ext2_inode_truncate: - push ebx ecx edx esi edi - - ; Save the inode. - push eax - - ; Read the inode. - mov ebx, [ebp + EXTFS.ext2_temp_inode] - call ext2_inode_read - test eax, eax - jnz .error - - mov eax, [ebx + EXT2_INODE_STRUC.i_size] - cmp ecx, eax - jge .success - - ; Save the size of the inode. - push eax - - ; ECX contains the size we've to truncate. - sub ecx, eax - not ecx - inc ecx - xor edx, edx - div [ebp + EXTFS.block_size] - - test edx, edx - jz .start_aligned - - ; Start isn't aligned, so deal with the non-aligned bytes. - mov esi, edx - - cmp esi, ecx - jbe @F - - ; If the size to truncate is smaller than the un-aligned bytes - ; we're going to have to mark neccessary bytes from the EOF - ; as 0. - push eax - call ext2_inode_read_entry - test eax, eax - pop eax - jnz .error_inode_size - - mov edi, [ebp + EXTFS.ext2_save_block] - sub edx, ecx - add edi, edx - - push ecx eax - xor eax, eax - rep stosb - pop eax ecx - - call ext2_inode_write_entry - test eax, eax - jnz .error_inode_size - - sub [esp], ecx - jmp .write_inode - - @@: - ; Since ECX is greater than or equal to the bytes here un-aligned - ; just free the block. - call ext2_inode_free_entry - - sub [esp], esi - sub ecx, esi - jz .write_inode - - .start_aligned: - cmp ecx, [ebp + EXTFS.block_size] - jb @F - - mov eax, [esp] - xor edx, edx - div [ebp + EXTFS.block_size] - dec eax - - call ext2_inode_free_entry - - test eax, eax - jnz .error_inode_size - - mov eax, [ebp + EXTFS.block_size] - sub ecx, eax - sub [esp], eax - jmp .start_aligned - - ; Handle the remaining bytes. - @@: - test ecx, ecx - jz .write_inode - - mov eax, [esp] - xor edx, edx - div [ebp + EXTFS.block_size] - dec eax - - push eax - call ext2_inode_read_entry - test eax, eax - pop eax - jnz .error_inode_size - - mov edi, [ebp + EXTFS.ext2_save_block] - mov edx, [ebp + EXTFS.block_size] - sub edx, ecx - add edi, edx - - push ecx eax - xor eax, eax - rep stosb - pop eax ecx - - call ext2_inode_write_entry - test eax, eax - jnz .error_inode_size - - sub [esp], ecx - - .write_inode: - mov ebx, [ebp + EXTFS.ext2_temp_inode] - pop eax - mov [ebx + EXT2_INODE_STRUC.i_size], eax - mov eax, [esp] - call ext2_inode_write - - test eax, eax - jnz .error - - .success: - xor eax, eax - - .ret: - add esp, 4 - - pop edi esi edx ecx ebx - ret - - .error_inode_size: - mov ebx, [ebp + EXTFS.ext2_temp_inode] - pop eax - mov [ebx + EXT2_INODE_STRUC.i_size], eax - mov eax, [esp] - call ext2_inode_write - - .error: - xor eax, eax - not eax - jmp .ret diff --git a/kernel/trunk/fs/ext2/resource.inc b/kernel/trunk/fs/ext2/resource.inc deleted file mode 100644 index 01b5b932c7..0000000000 --- a/kernel/trunk/fs/ext2/resource.inc +++ /dev/null @@ -1,226 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Contains common resource allocation + freeing code. ;; -;; ;; -;; Copyright (C) KolibriOS team 2013-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;--------------------------------------------------------------------- -; Frees a resource (block/inode). -; Input: eax = resource ID. -; edi = function pointer of ext2_bg_*_bitmap form, to -; get bitmap of resource. -; ecx = 0, block; 1, inode. -; ebp = pointer to EXTFS. -; Output: Block marked as free in block group. -; eax = error code. -;--------------------------------------------------------------------- -ext2_resource_free: - push ebx edx esi - - ; Get block group. - sub eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block] - xor edx, edx - div [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_per_group] - push eax edx - - call edi - test eax, eax - jz .fail - mov esi, eax - - ; Read the bitmap. - mov eax, ebx - mov edx, eax - mov ebx, [ebp + EXTFS.ext2_save_block] - call ext2_block_read - test eax, eax - jnz .fail - - pop eax - ; Mark bit free. - call bitmap_clear_bit - test eax, eax - jz @F - - ; No need to save anything. - xor eax, eax - - add esp, 4 - jmp .return - - @@: - mov eax, edx - mov ebx, [ebp + EXTFS.ext2_save_block] - call ext2_block_write - test eax, eax - jnz .fail - - ; Read the descriptor. - mov eax, [esp] - call ext2_bg_read_desc - test eax, eax - jz .fail_bg_desc_read - - lea eax, [eax + EXT2_BLOCK_GROUP_DESC.free_blocks_count] - shl ecx, 1 - add eax, ecx - inc word[eax] - - lea eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.free_block_count] - shl ecx, 1 - add eax, ecx - inc dword[eax] - - pop eax - call ext2_bg_write_desc - - .return: - pop esi edx ebx - ret - - .fail: - add esp, 4 - .fail_bg_desc_read: - add esp, 4 - xor eax, eax - not eax - jmp .return - -;--------------------------------------------------------------------- -; Allocates a resource. -; Input: eax = inode ID for "preference". -; ebp = pointer to EXTFS. -; [esp + 4], func pointer to ext2_bg_*_bitmap -; [esp + 8], pointer to free_*_count in SB. -; [esp + 12], *_per_group -; [esp + 16], offset to free_*_count in bg descriptor. -; [esp + 20], *_count -; Output: Resource marked as set in block group. -; eax = error code. -; ebx = resource ID. -;--------------------------------------------------------------------- -ext2_resource_alloc: - ; Block allocation is a pretty serious area, since bad allocation - ; can lead to fragmentation. Thus, the best way to allocate that - ; comes to mind is to allocate around an inode as much as possible. - ; On the other hand, this isn't about a single inode/file/directory, - ; and focusing just around the preferred inode would lead to - ; congestion. Thus, after much thought, the chosen allocation algorithm - ; is to search forward, then backward. - push ecx edx esi edi - - cmp dword[esp + 16 + 8], 0 - jnz @F - - ; No free blocks. - xor eax, eax - not eax - pop edi esi edx ecx - ret 20 - - @@: - ; Calculate which block group the preferred inode belongs to. - dec eax - xor edx, edx - - ; EAX = block group. - div [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group] - push eax - push eax - - mov edi, .forward - - .test_block_group: - call dword[esp + 16 + 8 + 4] - test eax, eax - jz .fail - mov esi, eax - - mov eax, ebx - mov edx, eax - mov ebx, [ebp + EXTFS.ext2_save_block] - call ext2_block_read - test eax, eax - jnz .fail - - mov ecx, [esp + 16 + 8 + 12] - call ext2_find_free_bit - cmp eax, 0xFFFFFFFF - jne @F - - mov eax, edi - jmp eax - - @@: - mov ecx, eax - - mov eax, edx - mov ebx, [ebp + EXTFS.ext2_save_block] - call ext2_block_write - test eax, eax - jnz .fail - - ; ecx: the index of the matched entry. - ; [esp]: block group where we found. - ; [esp + 4]: starting block group. - ; esi: block group descriptor. - mov eax, [esp] ; Index of block group in which we found. - mul dword[esp + 16 + 8 + 12] - add eax, ecx - mov ebx, eax - - mov eax, [esp + 16 + 8 + 8] - dec dword[eax] - - mov eax, esi - add eax, [esp + 16 + 8 + 16] - dec word[eax] - - pop eax - call ext2_bg_write_desc - - add esp, 4 - jmp .return - - ; Continue forward. - .forward: - inc dword[esp] - mov eax, [esp] - mul dword[esp + 16 + 8 + 12] - cmp eax, [esp + 16 + 8 + 20] - jbe @F - - ; We need to go backward. - mov eax, [esp + 4] - mov [esp], eax - mov edi, .backward - jmp .backward - - @@: - mov eax, [esp] - jmp .test_block_group - - ; Continue backward. - .backward: - cmp dword[esp], 0 - je .fail - - dec dword[esp] - mov eax, [esp] - jmp .test_block_group - - .return: - pop edi esi edx ecx - ret 20 - - .fail: - add esp, 8 - xor eax, eax - not eax - jmp .return \ No newline at end of file diff --git a/kernel/trunk/fs/fs_common.inc b/kernel/trunk/fs/fs_common.inc new file mode 100644 index 0000000000..2a87b7e535 --- /dev/null +++ b/kernel/trunk/fs/fs_common.inc @@ -0,0 +1,142 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License. ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +fsReadCMOS: + out 70h, al + in al, 71h + xor ah, ah + shl ax, 4 + shr al, 4 + aad + ret + +fsGetTime: + mov al, 7 + call fsReadCMOS + ror eax, 8 + mov al, 8 + call fsReadCMOS + ror eax, 8 + mov al, 9 + call fsReadCMOS + add eax, 2000 + ror eax, 16 + push eax + xor eax, eax + call fsReadCMOS + ror eax, 8 + mov al, 2 + call fsReadCMOS + ror eax, 8 + mov al, 4 + call fsReadCMOS + ror eax, 16 + push eax + mov esi, esp + add esp, 8 +fsCalculateTime: +; in: esi -> data block +; out: eax = seconds since 01.01.2001 + movzx eax, word [esi+6] + sub eax, 2001 + jnc @f + xor eax, eax +@@: + mov edx, months + mov ebx, eax + inc eax + test eax, 3 + jnz @f + add edx, 12 +@@: + movzx eax, byte [esi+5] + dec eax + xor ecx, ecx +@@: + dec eax + js @f + add cl, [edx+eax] + adc ch, 0 + jmp @b +@@: + mov eax, ebx ; years + mov edx, 365 + mul edx + shr ebx, 2 + add eax, ebx + add eax, ecx + mov bl, [esi+4] + dec eax + add eax, ebx ; days + mov dl, 24 + mul edx + mov bl, [esi+2] + add eax, ebx ; hours + mov ecx, 60 + mul ecx + mov bl, [esi+1] + add eax, ebx ; minutes + mul ecx + mov bl, [esi] + add eax, ebx + ret + +iglobal +months db 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +months2 db 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +endg + +fsTime2bdfe: +; in: eax = seconds since 01.01.2001 +; edi -> data block +; out: edi = edi+8 + xor edx, edx + mov ecx, 60 + div ecx + mov [edi], dl + xor edx, edx + div ecx + mov [edi+1], dl + xor edx, edx + mov cl, 24 + div ecx + mov [edi+2], dx + xor edx, edx + mov cx, 365 + div ecx + mov ebx, eax + add ebx, 2001 + shr eax, 2 + sub edx, eax + jns @f + dec ebx + add edx, 365 + test ebx, 3 + jnz @f + inc edx +@@: + xor eax, eax + mov ecx, months-1 + test ebx, 3 + jnz @f + add ecx, 12 +@@: + inc ecx + inc eax + sub dl, [ecx] + jnc @b + dec dh + jns @b + add dl, [ecx] + inc edx + mov [edi+4], dl + mov [edi+5], al + mov [edi+6], bx + add edi, 8 + ret diff --git a/kernel/trunk/fs/fs_lfn.inc b/kernel/trunk/fs/fs_lfn.inc index c134607a20..6442606d89 100644 --- a/kernel/trunk/fs/fs_lfn.inc +++ b/kernel/trunk/fs/fs_lfn.inc @@ -1,7 +1,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; -;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; +;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License. ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -965,3 +965,11 @@ get_full_file_name: jz .ret.ok mov byte [edi-1], '/' jmp .set_copy_cont + +include "parse_fn.inc" +include "fs_common.inc" +include "iso9660.inc" ; read for CD filesystem +include "fat.inc" +include "ntfs.inc" +include "ext.inc" +include "xfs.asm" diff --git a/kernel/trunk/fs/ntfs.inc b/kernel/trunk/fs/ntfs.inc index 4954c83a31..3903908e7f 100644 --- a/kernel/trunk/fs/ntfs.inc +++ b/kernel/trunk/fs/ntfs.inc @@ -1,13 +1,36 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; +;; Distributed under terms of the GNU General Public License. ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ -; NTFS driver +; NTFS external functions +; in: +; ebx -> parameter structure of sysfunc 70 +; ebp -> NTFS structure +; [esi]+[[esp+4]] = name +; out: +; eax, ebx = return values for sysfunc 70 +iglobal +align 4 +ntfs_user_functions: + dd ntfs_free + dd (ntfs_user_functions_end - ntfs_user_functions - 4) / 4 + dd ntfs_ReadFile + dd ntfs_ReadFolder + dd ntfs_CreateFile + dd ntfs_WriteFile + dd ntfs_SetFileEnd + dd ntfs_GetFileInfo + dd ntfs_SetFileInfo + dd 0 + dd ntfs_Delete + dd ntfs_CreateFolder +ntfs_user_functions_end: +endg ; Basic concepts: ; File is a FileRecord in the $MFT. @@ -95,7 +118,7 @@ namespace = 51h fileName = 52h struct NTFS PARTITION -Lock MUTEX ? ; Currently operations with one partition +Lock MUTEX ; Currently operations with one partition ; can not be executed in parallel since the legacy code is not ready. sectors_per_cluster dd ? mft_cluster dd ? ; location @@ -151,31 +174,6 @@ attrlist_mft_buf rb 1024 bitmap_buf rb 1024 ends -; NTFS external functions -; in: -; ebx -> parameter structure of sysfunc 70 -; ebp -> NTFS structure -; [esi]+[esp+4] = name -; out: -; eax, ebx = return values for sysfunc 70 -iglobal -align 4 -ntfs_user_functions: - dd ntfs_free - dd (ntfs_user_functions_end - ntfs_user_functions - 4) / 4 - dd ntfs_ReadFile - dd ntfs_ReadFolder - dd ntfs_CreateFile - dd ntfs_WriteFile - dd ntfs_SetFileEnd - dd ntfs_GetFileInfo - dd ntfs_SetFileInfo - dd 0 - dd ntfs_Delete - dd ntfs_CreateFolder -ntfs_user_functions_end: -endg - ntfs_test_bootsec: ; in: ebx -> buffer, edx = size of partition ; out: CF=1 -> invalid @@ -258,7 +256,14 @@ ntfs_test_bootsec: stc ret +; Mount if it's a valid NTFS partition. ntfs_create_partition: +; in: +; ebp -> PARTITION structure +; ebx -> boot sector +; ebx+512 -> buffer +; out: +; eax -> NTFS structure, 0 = not NTFS cmp dword [esi+DISK.MediaInfo.SectorSize], 512 jnz .nope mov edx, dword [ebp+PARTITION.Length] @@ -1684,7 +1689,7 @@ ntfs_ReadFolder: mov eax, 0x10 stosd scasd - push edx + push ebx ecx edx mov eax, dword [ebp+NTFS.bitmap_buf] mov edx, dword [ebp+NTFS.bitmap_buf+4] call ntfs_datetime_to_bdfe @@ -1694,7 +1699,7 @@ ntfs_ReadFolder: mov eax, dword [ebp+NTFS.bitmap_buf+8] mov edx, dword [ebp+NTFS.bitmap_buf+0xC] call ntfs_datetime_to_bdfe - pop edx + pop edx ecx ebx xor eax, eax stosd stosd @@ -1778,7 +1783,7 @@ ntfs_direntry_to_bdfe: @@: stosd scasd - push edx + push ebx ecx edx mov eax, [esi+fileCreated] mov edx, [esi+fileCreated+4] call ntfs_datetime_to_bdfe @@ -1788,91 +1793,26 @@ ntfs_direntry_to_bdfe: mov eax, [esi+fileModified] mov edx, [esi+fileModified+4] call ntfs_datetime_to_bdfe - pop edx + pop edx ecx ebx mov eax, [esi+fileRealSize] stosd mov eax, [esi+fileRealSize+4] stosd ret -iglobal -months db 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -months2 db 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -endg - ntfs_datetime_to_bdfe: -; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC - push ebx ecx - mov ebx, eax - mov eax, edx - xor edx, edx +; in: edx:eax = seconds since 01.01.1601 x10000000 +; edi -> data block +; out: edi = edi+8 + sub eax, 3365781504 + sbb edx, 29389701 mov ecx, 10000000 - div ecx - xchg eax, ebx - div ecx -.forEXT: - xchg eax, ebx + cmp edx, ecx + jc @f xor edx, edx - mov ecx, 60 - div ecx - xchg eax, ebx - div ecx - mov [edi], dl - mov edx, ebx -; edx:eax = number of minutes - div ecx - mov [edi+1], dl -; eax = number of hours - xor edx, edx - mov cl, 24 - div ecx - mov [edi+2], dx -; eax = number of days since January 1, 1601 - xor edx, edx - mov cx, 365 - div ecx - mov ebx, eax - add ebx, 1601 - shr eax, 2 - sub edx, eax - mov cl, 25 - div cl - xor ah, ah - add edx, eax - shr eax, 2 - sub edx, eax - jns @f - dec ebx - add edx, 365 - test bl, 3 - jnz @f - inc edx @@: - xor eax, eax - mov ecx, months-1 - test bl, 3 - jnz @f - add ecx, 12 -@@: - inc ecx - inc eax - sub dl, [ecx] - jnc @b - dec dh - jns @b - add dl, [ecx] - inc edx - mov [edi+4], dl - mov [edi+5], al - mov [edi+6], bx - add edi, 8 - pop ecx ebx - ret - -.sec: - push ebx ecx - mov ebx, edx - jmp .forEXT + div ecx + jmp fsTime2bdfe ;---------------------------------------------------------------- ntfs_GetFileInfo: @@ -4179,90 +4119,19 @@ ntfs_SetFileEnd: call ntfsSpaceClean jmp ntfsDone -ntfsReadCMOS: - out 70h, al - in al, 71h - xor ah, ah - shl ax, 4 - shr al, 4 - aad - ret - ntfsGetTime: - mov al, 7 - call ntfsReadCMOS - ror eax, 8 - mov al, 8 - call ntfsReadCMOS - ror eax, 8 - mov al, 9 - call ntfsReadCMOS - add eax, 2000 - ror eax, 16 - push eax - xor eax, eax - call ntfsReadCMOS - ror eax, 8 - mov al, 2 - call ntfsReadCMOS - ror eax, 8 - mov al, 4 - call ntfsReadCMOS - ror eax, 16 - push eax - mov esi, esp - add esp, 8 + call fsGetTime + jmp @f + ntfsCalculateTime: ; in: esi -> data block -; out: edx:eax = time - movzx eax, word [esi+6] - sub eax, 2001 - jnc @f - xor eax, eax +; out: edx:eax = seconds since 01.01.1601 x10000000 + call fsCalculateTime @@: - mov edx, months - mov ebx, eax - inc eax - test eax, 3 - jnz @f - add edx, 12 -@@: - movzx eax, byte [esi+5] - dec eax - xor ecx, ecx -@@: - dec eax - js @f - add cl, [edx+eax] - adc ch, 0 - jmp @b -@@: - mov eax, ebx - mov edx, 365 + mov edx, 10000000 mul edx - shr ebx, 2 - add eax, ebx - add eax, ecx - mov bl, [esi+4] - add eax, ebx - add eax, 400*365+100-4 - mov dl, 24 - mul edx - mov bl, [esi+2] - add eax, ebx - mov ecx, 60 - mul ecx - mov bl, [esi+1] - add eax, ebx - mul ecx - mov bl, [esi] - add ebx, eax - mov eax, edx - mov ecx, 10000000 - mul ecx - xchg eax, ebx - mul ecx - add edx, ebx + add eax, 3365781504 + adc edx, 29389701 ret ;---------------------------------------------------------------- diff --git a/kernel/trunk/fs/parse_fn.inc b/kernel/trunk/fs/parse_fn.inc index 851de54fd4..4cbc99cb6d 100644 --- a/kernel/trunk/fs/parse_fn.inc +++ b/kernel/trunk/fs/parse_fn.inc @@ -1,7 +1,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; -;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; +;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License. ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -391,3 +391,72 @@ ansi2uni_char: .unk: mov al, '_' ret + +utf8_to_cp866: +; in: esi, edi, ecx +; destroys esi, edi, ecx, eax + call utf8to16 + js utf8to16.ret + call uni2ansi_char + stosb + jmp utf8_to_cp866 + +utf8to16: +; in: +; esi -> string +; ecx = byte counter +; out: +; SF=1 -> end +; ax = UTF-16 char +; changes esi, ecx + dec ecx + js .ret + lodsb + test al, al + jns .got + shl al, 2 + jnc utf8to16 +@@: + shl ax, 8 + dec ecx + js .ret + lodsb + test al, al + jns .got + shl al, 2 + jc @b + shr ah, 2 + shl ax, 3 + jnc @f + shl eax, 3 + dec ecx + js .ret + lodsb + test al, al + jns .got + shl al, 2 + jc @b + shr eax, 2 + ret + +@@: + shr ax, 5 + ret + +.got: + xor ah, ah +.ret: + ret + +strlen: +; in: esi -> source +; out: ecx = length + push edi eax + or ecx, -1 + mov edi, esi + xor eax, eax + repnz scasb + inc ecx + not ecx + pop eax edi + ret diff --git a/kernel/trunk/fs/xfs.asm b/kernel/trunk/fs/xfs.asm index 136dfaecfc..066cb5d4c3 100644 --- a/kernel/trunk/fs/xfs.asm +++ b/kernel/trunk/fs/xfs.asm @@ -1,29 +1,46 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; -;; Copyright (C) KolibriOS team 2013-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; +;; Copyright (C) KolibriOS team 2013-2016. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License. ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ +; XFS external functions +; in: +; ebx -> parameter structure of sysfunc 70 +; ebp -> XFS structure +; [esi]+[[esp+4]] = name +; out: +; eax, ebx = return values for sysfunc 70 +iglobal +align 4 +xfs_user_functions: + dd xfs_free + dd (xfs_user_functions_end - xfs_user_functions - 4) / 4 + dd xfs_ReadFile + dd xfs_ReadFolder + dd 0;xfs_CreateFile + dd 0;xfs_WriteFile + dd 0;xfs_SetFileEnd + dd xfs_GetFileInfo + dd 0;xfs_SetFileInfo + dd 0 + dd 0;xfs_Delete + dd 0;xfs_CreateFolder +xfs_user_functions_end: +endg include 'xfs.inc' -; -; This file contains XFS related code. -; For more information on XFS check sources below. -; -; 1. XFS Filesystem Structure, 2nd Edition, Revision 1. Silicon Graphics Inc. 2006 -; 2. Linux source http://kernel.org -; - - -; test partition type (valid XFS one?) -; alloc and fill XFS (see xfs.inc) structure -; this function is called for each partition -; returns 0 (not XFS or invalid) / pointer to partition structure +; Mount if it's a valid XFS partition. xfs_create_partition: +; in: +; ebp -> PARTITION structure +; ebx -> boot sector +; out: +; eax -> XFS structure, 0 = not XFS push ebx ecx edx esi edi cmp dword [esi+DISK.MediaInfo.SectorSize], 512 jnz .error @@ -94,7 +111,7 @@ xfs_create_partition: mov dword[edi + XFS.rootino + 0], eax ; endian mov eax, dword[ebx + xfs_sb.sb_rootino + 0] ; 64bit bswap eax ; number - mov dword[edi + XFS.rootino + 4], eax ; + mov dword[edi + XFS.rootino + 4], eax ; mov eax, [edi + XFS.blocksize] mov ecx, [edi + XFS.dirblklog] @@ -211,25 +228,6 @@ xfs_create_partition: ret -iglobal -align 4 -xfs_user_functions: - dd xfs_free - dd (xfs_user_functions_end - xfs_user_functions - 4) / 4 - dd xfs_Read - dd xfs_ReadFolder - dd 0;xfs_Rewrite - dd 0;xfs_Write - dd 0;xfs_SetFileEnd - dd xfs_GetFileInfo - dd 0;xfs_SetFileInfo - dd 0 - dd 0;xfs_Delete - dd 0;xfs_CreateFolder -xfs_user_functions_end: -endg - - ; lock partition access mutex proc xfs_lock ;DEBUGF 1,"xfs_lock\n" @@ -510,10 +508,10 @@ DEBUGF 1,"xfs_dir_get_bdfes: %d entries from %d\n",[esp+8],[esp+4] add eax, eax ; 4+4=8, iff i8count != 0 @@: mov dword[edx + 12], 0 ; reserved - mov dword[edx + 16], 0 ; - mov dword[edx + 20], 0 ; - mov dword[edx + 24], 0 ; - mov dword[edx + 28], 0 ; + mov dword[edx + 16], 0 ; + mov dword[edx + 20], 0 ; + mov dword[edx + 24], 0 ; + mov dword[edx + 28], 0 ; add edx, 32 lea esi, [ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.parent + eax] dec ecx @@ -642,10 +640,10 @@ DEBUGF 1,"xfs_dir_get_bdfes: %d entries from %d\n",[esp+8],[esp+4] mov [ebp + XFS.entries_read], eax ;DEBUGF 1,"actually read entries: %d\n",eax mov dword[edx + 12], 0 ; reserved - mov dword[edx + 16], 0 ; - mov dword[edx + 20], 0 ; - mov dword[edx + 24], 0 ; - mov dword[edx + 28], 0 ; + mov dword[edx + 16], 0 ; + mov dword[edx + 20], 0 ; + mov dword[edx + 24], 0 ; + mov dword[edx + 28], 0 ; add ebx, xfs_dir2_block.u mov ecx, [esp + 24] ; start entry number @@ -742,10 +740,10 @@ DEBUGF 1,"xfs_dir_get_bdfes: %d entries from %d\n",[esp+8],[esp+4] mov [edx + 4], eax ; number of actually read entries mov dword[edx + 12], 0 ; reserved - mov dword[edx + 16], 0 ; - mov dword[edx + 20], 0 ; - mov dword[edx + 24], 0 ; - mov dword[edx + 28], 0 ; + mov dword[edx + 16], 0 ; + mov dword[edx + 20], 0 ; + mov dword[edx + 24], 0 ; + mov dword[edx + 28], 0 ; mov eax, [ebp + XFS.cur_dirblock] add eax, [ebp + XFS.dirblocksize] @@ -886,10 +884,10 @@ DEBUGF 1,"xfs_dir_get_bdfes: %d entries from %d\n",[esp+8],[esp+4] mov [edx + 4], eax ; number of actually read entries mov dword[edx + 12], 0 ; reserved - mov dword[edx + 16], 0 ; - mov dword[edx + 20], 0 ; - mov dword[edx + 24], 0 ; - mov dword[edx + 28], 0 ; + mov dword[edx + 16], 0 ; + mov dword[edx + 20], 0 ; + mov dword[edx + 24], 0 ; + mov dword[edx + 28], 0 ; mov eax, [ebp + XFS.cur_dirblock] add eax, [ebp + XFS.dirblocksize] @@ -1739,28 +1737,22 @@ xfs_get_inode_info: mov eax, [edx + xfs_inode.di_core.di_ctime.t_sec] bswap eax push edx - xor edx, edx - add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec + sub eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60 + call fsTime2bdfe pop edx mov eax, [edx + xfs_inode.di_core.di_atime.t_sec] bswap eax push edx - xor edx, edx - add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec + sub eax, 978307200 + call fsTime2bdfe pop edx mov eax, [edx + xfs_inode.di_core.di_mtime.t_sec] bswap eax push edx - xor edx, edx - add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec + sub eax, 978307200 + call fsTime2bdfe pop edx .quit: @@ -1947,18 +1939,16 @@ xfs_GetFileInfo: ;---------------------------------------------------------------- -; xfs_Read - XFS implementation of reading a file +; xfs_ReadFile - XFS implementation of reading a file ; in: ebp = pointer to XFS structure ; in: esi+[esp+4] = name ; in: ebx = pointer to parameters from sysfunc 70 ; out: eax, ebx = return values for sysfunc 70 ;---------------------------------------------------------------- -xfs_Read: +xfs_ReadFile: push ebx ecx edx esi edi call xfs_lock - add esi, [esp + 24] -;DEBUGF 1,"xfs_Read: %d %d |%s|\n",[ebx+4],[ebx+12],esi stdcall xfs_get_inode, esi mov ecx, edx or ecx, eax @@ -2353,7 +2343,7 @@ xfs_dir2_node_get_numfiles: test eax, eax jnz .error jmp .common - + .leaf: ;DEBUGF 1,".leaf\n" movzx ecx, word[ebx + xfs_dir2_leaf.hdr.count] @@ -2514,7 +2504,7 @@ xfs_dir2_btree_get_numfiles: test eax, eax jnz .error jmp .common - + .leaf: ;DEBUGF 1,".leaf\n" movzx ecx, word[ebx + xfs_dir2_leaf.hdr.count] @@ -2750,7 +2740,7 @@ DEBUGF 1,".root.not_root\n" jmp .quit .leaf: - + jmp .quit .error: diff --git a/kernel/trunk/gui/font.inc b/kernel/trunk/gui/font.inc index de566fea17..3458e87abd 100644 --- a/kernel/trunk/gui/font.inc +++ b/kernel/trunk/gui/font.inc @@ -141,40 +141,18 @@ deltaToScreen = 28 .drawUTF8: dec dword [esp] js .done -@@: - movzx ebx, byte [esi] - inc esi - test bl, bl + mov ecx, 256 + xor eax, eax + call utf8to16 + test ax, ax jz .done - jns .valid - shl bx, 10 - jnc @b - mov bl, [esi] - test bl, bl - jns @b - shl bl, 2 - jc @b - shr bh, 2 - shr bx, 2 - inc esi - cmp bx, 1419 - jc .valid - shl bh, 4 - jns @f -.tail: - mov bl, [esi] - shl bl, 1 - jnc @b - js @b - inc esi - shl bh, 1 - js .tail + cmp eax, 1419 + jc @f + xor eax, eax @@: - xor ebx, ebx -.valid: + shl eax, 4 + lea ebx, [eax+fontUni] pushd esi edi 16 - shl ebx, 4 - add ebx, fontUni mov esi, [esp+12+fontMultiplier] call drawChar imul esi, 8*4 diff --git a/kernel/trunk/kernel32.inc b/kernel/trunk/kernel32.inc index bbf421ec57..b3d503028c 100644 --- a/kernel/trunk/kernel32.inc +++ b/kernel/trunk/kernel32.inc @@ -1,132 +1,70 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; -;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; KERNEL32.INC ;; -;; ;; -;; Included 32 bit kernel files for MenuetOS ;; -;; ;; -;; This file is kept separate as it will be easier to ;; -;; maintain and compile with an automated SETUP program ;; -;; in the future. ;; +;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License. ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $Revision$ -; Core functions -include "core/sync.inc" ; macros for synhronization objects -include "core/sys32.inc" ; process management -include "core/sched.inc" ; process scheduling -include "core/syscall.inc" ; system call -include "core/fpu.inc" ; all fpu/sse support +include "core/sync.inc" ; macros for synhronization objects +include "core/sys32.inc" ; process management +include "core/sched.inc" ; process scheduling +include "core/syscall.inc" +include "core/fpu.inc" ; all fpu/sse support include "core/memory.inc" include "core/mtrr.inc" -include "core/heap.inc" ; kernel and app heap -include "core/malloc.inc" ; small kernel heap +include "core/heap.inc" +include "core/malloc.inc" ; small kernel heap include "core/taskman.inc" include "core/dll.inc" -include "core/peload.inc" ; +include "core/peload.inc" include "core/exports.inc" include "core/string.inc" -include "core/v86.inc" ; virtual-8086 manager -include "core/irq.inc" ; irq handling functions -include "core/apic.inc" ; Interrupt Controller functions +include "core/v86.inc" ; 16-bit mode machine +include "core/irq.inc" ; interrupt handling functions +include "core/apic.inc" include "core/timers.inc" -include "core/clipboard.inc" ; custom clipboard +include "core/clipboard.inc" +include "core/conf_lib.inc" +include "core/ext_lib.inc" ; load external library + +include "boot/shutdown.inc" ; kernel shutdown + +include "video/vesa20.inc" +include "video/blitter.inc" +include "video/vga.inc" ; VGA 16 color functions +include "video/cursors.inc" +include "video/framebuffer.inc" -; GUI stuff include "gui/window.inc" include "gui/event.inc" include "gui/font.inc" include "gui/button.inc" - -include "boot/shutdown.inc" ; kernel shutdown - -; file system - -include "blkdev/disk.inc" ; support for plug-n-play disks -include "blkdev/disk_cache.inc" ; caching for plug-n-play disks -include "blkdev/rd.inc" ; ramdisk read /write -include "fs/fat.inc" ; read / write for fat filesystem -include "fs/ntfs.inc" ; read / write for ntfs filesystem -include "fs/fs_lfn.inc" ; syscall, version 2 -include "fs/iso9660.inc" ; read for iso9660 filesystem CD -include "fs/ext2/ext2.asm" ; read / write for ext2 filesystem -include "fs/xfs.asm" ; read / write for xfs filesystem - -; sound - -include "sound/playnote.inc" ; player Note for Speaker PC - -; display - -;include "video/vesa12.inc" ; Vesa 1.2 functions -include "video/vesa20.inc" ; Vesa 2.0 functions -include "video/blitter.inc" -include "video/vga.inc" ; VGA 16 color functions -include "video/cursors.inc" ; cursors functions -include "video/framebuffer.inc" ; framebuffer functions - -; Network Interface & TCPIP Stack - -include "network/stack.inc" - -;include "drivers/uart.inc" - - -; Mouse pointer - -include "gui/mouse.inc" - -; Window skinning - -include "gui/skincode.inc" - -; Pci functions - -include "bus/pci/pci32.inc" - -; USB functions -include "bus/usb/init.inc" - -; Floppy drive controller - -include "blkdev/fdc.inc" -include "blkdev/flp_drv.inc" - -; IDE cache -include "blkdev/ide_cache.inc" - -; HD drive controller -include "blkdev/hd_drv.inc" -; Access through BIOS -include "blkdev/bd_drv.inc" - -; CD drive controller - -include "blkdev/cd_drv.inc" - -; Character devices +include "gui/mouse.inc" ; cursor +include "gui/skincode.inc" ; windows' skin include "hid/keyboard.inc" include "hid/mousedrv.inc" +include "hid/set_dtc.inc" ; setting date,time,clock and alarm-clock -; setting date,time,clock and alarm-clock +include "sound/playnote.inc" ; player Note for PC Speaker -include "hid/set_dtc.inc" +include "bus/pci/pci32.inc" +include "bus/usb/init.inc" -;% -include +include "blkdev/flp_drv.inc" ; floppy driver +include "blkdev/fdc.inc" +include "blkdev/cd_drv.inc" ; CD driver +include "blkdev/ide_cache.inc" ; CD cache +include "blkdev/hd_drv.inc" ; HDD driver +include "blkdev/bd_drv.inc" ; BIOS disks driver +include "blkdev/rd.inc" ; ramdisk driver +include "blkdev/disk.inc" ; support for plug-n-play disks +include "blkdev/disk_cache.inc" ; caching for plug-n-play disks -;parser file names -include "fs/parse_fn.inc" +include "fs/fs_lfn.inc" ; sysfunction 70 -; work with conf lib -include "core/conf_lib.inc" +include "network/stack.inc" -; load external lib -include "core/ext_lib.inc" - -; list of external functions -include "imports.inc" +include "imports.inc" ; list of external functions