diff --git a/kernel/trunk/fs/ext2/blocks.asm b/kernel/trunk/fs/ext2/blocks.asm deleted file mode 100644 index 60b562399d..0000000000 --- a/kernel/trunk/fs/ext2/blocks.asm +++ /dev/null @@ -1,408 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Contains ext2 block handling code. ;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; -;; Distributed under the terms of the new BSD license. ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;--------------------------------------------------------------------- -; 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 diff --git a/kernel/trunk/fs/ext2/inode.asm b/kernel/trunk/fs/ext2/inode.asm deleted file mode 100644 index c9d4c5a464..0000000000 --- a/kernel/trunk/fs/ext2/inode.asm +++ /dev/null @@ -1,1175 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Contains ext2 inode handling code. ;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; -;; Distributed under the terms of the new BSD license. ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; KSOC_EXT2_WRITE_END_TODO: clean this up. -;--------------------------------------------------------------------- -; 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 - -;--------------------------------------------------------------------- -; 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_set_inode_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 - - ; TODO: fix to have correct preference. - mov eax, EXT2_ROOT_INO - call ext2_block_calloc - 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 - - mov eax, EXT2_ROOT_INO - call ext2_block_calloc - 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 - - ; TODO: fix to have correct preference. - mov eax, EXT2_ROOT_INO - call ext2_block_calloc - 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 - - ; TODO: fix to have correct preference. - mov eax, EXT2_ROOT_INO - call ext2_block_calloc - 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 - - ; TODO: fix to have correct preference. - mov eax, EXT2_ROOT_INO - call ext2_block_calloc - 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_get_inode_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] - 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] - 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] - - 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] - mov ebx, [ebp + EXTFS.ext2_temp_block] - call ext2_block_read - test eax, eax - jnz @F - - ; Get the block ID. - 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 - -;--------------------------------------------------------------------- -; 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_get_inode_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_get_inode_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_get_inode_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_set_inode_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_get_inode_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_get_inode_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 \ No newline at end of file diff --git a/kernel/trunk/fs/ext2/resource.asm b/kernel/trunk/fs/ext2/resource.asm deleted file mode 100644 index c0b38b96dc..0000000000 --- a/kernel/trunk/fs/ext2/resource.asm +++ /dev/null @@ -1,223 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Contains common resource allocation + freeing code. ;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; -;; Distributed under the terms of the new BSD license. ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;--------------------------------------------------------------------- -; 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 defragmentation. 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 though, 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