forked from KolibriOS/kolibrios
ext2 write support added; CreateFolder and Delete complete.
git-svn-id: svn://kolibrios.org@3935 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
bf1716aa88
commit
f6725d41ef
File diff suppressed because it is too large
Load Diff
408
kernel/trunk/fs/ext2/blocks.asm
Normal file
408
kernel/trunk/fs/ext2/blocks.asm
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; 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
|
1221
kernel/trunk/fs/ext2/ext2.asm
Normal file
1221
kernel/trunk/fs/ext2/ext2.asm
Normal file
File diff suppressed because it is too large
Load Diff
648
kernel/trunk/fs/ext2/ext2.inc
Normal file
648
kernel/trunk/fs/ext2/ext2.inc
Normal file
@ -0,0 +1,648 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; Contains ext2 structures, and macros. ;;
|
||||||
|
;; ;;
|
||||||
|
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||||
|
;; Distributed under the terms of the new BSD license. ;;
|
||||||
|
;; ;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
; 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.
|
||||||
|
|
||||||
|
; 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
|
1175
kernel/trunk/fs/ext2/inode.asm
Normal file
1175
kernel/trunk/fs/ext2/inode.asm
Normal file
File diff suppressed because it is too large
Load Diff
223
kernel/trunk/fs/ext2/resource.asm
Normal file
223
kernel/trunk/fs/ext2/resource.asm
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; 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
|
@ -191,7 +191,7 @@ include "fs/fat12.inc" ; read / write for fat12 filesystem
|
|||||||
include "blkdev/rd.inc" ; ramdisk read /write
|
include "blkdev/rd.inc" ; ramdisk read /write
|
||||||
include "fs/fs_lfn.inc" ; syscall, version 2
|
include "fs/fs_lfn.inc" ; syscall, version 2
|
||||||
include "fs/iso9660.inc" ; read for iso9660 filesystem CD
|
include "fs/iso9660.inc" ; read for iso9660 filesystem CD
|
||||||
include "fs/ext2.inc" ; read / write for ext2 filesystem
|
include "fs/ext2/ext2.asm" ; read / write for ext2 filesystem
|
||||||
include "fs/xfs.asm" ; read / write for xfs filesystem
|
include "fs/xfs.asm" ; read / write for xfs filesystem
|
||||||
|
|
||||||
; sound
|
; sound
|
||||||
|
Loading…
Reference in New Issue
Block a user