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 "fs/fs_lfn.inc" ; syscall, version 2
|
||||
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
|
||||
|
||||
; sound
|
||||
|
Loading…
Reference in New Issue
Block a user