Compare commits

..

No commits in common. "ccaa159a73eb4a06273b2a1c2a097806e2f8fca1" and "b0ff2392a15e1d222e51247cfc3ce0350c9ceeb3" have entirely different histories.

5 changed files with 114 additions and 121 deletions

View File

@ -26,8 +26,6 @@ read_user_command_line:
cmpb $'\b', %al
je .read_user_command_line_backspace
cmpb $0x7F, %al
je .read_user_command_line_backspace
# Not sure if some BIOSes return '\n' as enter, but check it just in case
cmpb $'\r', %al

View File

@ -389,8 +389,10 @@ find_root_partition:
# increment 8 byte entry array lba
incl 0(%esp)
adcl $0, 4(%esp)
jnc .find_root_partition_no_overflow
incl 4(%esp)
.find_root_partition_no_overflow:
# loop to read next section if entries remaining
cmpl $0, 12(%esp)
jnz .find_root_partition_read_entry_section
@ -414,10 +416,12 @@ find_root_partition:
# ebx:eax -= first lba - 1
subl (root_partition_entry + 36), %ebx
movl (root_partition_entry + 32), %ecx
movl (root_partition_entry + 32), %ecx;
decl %ecx
subl %ecx, %eax
sbbl $0, %ebx
jnc .find_root_partition_count_sub_no_carry
decl %ebx
.find_root_partition_count_sub_no_carry:
# ecx: min(partition count, 0xFFFFFFFF)
movl $0xFFFFFFFF, %edx

View File

@ -2,7 +2,9 @@
.set SECTOR_SHIFT, 9
.set SECTOR_SIZE, 1 << SECTOR_SHIFT
.set EXT2_MAX_BLOCK_SIZE, 4096
# FIXME: don't assume 1024 byte blocks
.set EXT2_BLOCK_SHIFT, 10
.set EXT2_BLOCK_SIZE, 1 << EXT2_BLOCK_SHIFT
.set EXT2_SUPERBLOCK_SIZE, 264
.set EXT2_BGD_SHIFT, 5
.set EXT2_BGD_SIZE, 1 << EXT2_BGD_SHIFT
@ -16,7 +18,6 @@
.set EXT2_S_IFREG, 0x8000
# superblock offsets
.set s_first_data_block, 20
.set s_log_block_size, 24
.set s_inodes_per_group, 40
.set s_magic, 56
@ -65,7 +66,9 @@ has_ext2_filesystem:
# from byte offset 1024
addl $(1024 / SECTOR_SIZE), %eax
adcw $0, %bx
jnc .has_ext2_filesystem_no_overflow
incw %bx
.has_ext2_filesystem_no_overflow:
# into sector buffer
movw $ext2_block_buffer, %di
@ -87,16 +90,11 @@ has_ext2_filesystem:
movl (ext2_superblock_buffer + s_log_block_size), %ecx
testl $0xFFFFFF00, %ecx
jnz .has_ext2_filesystem_unsupported_block_size
# verify 1024 << s_log_block_size <= EXT2_MAX_BLOCK_SIZE
# verify 1024 << s_log_block_size == EXT2_BLOCK_SIZE
movl $1024, %eax
shll %cl, %eax
cmpl $EXT2_MAX_BLOCK_SIZE, %eax
ja .has_ext2_filesystem_unsupported_block_size
# fill block size and shift
movl %eax, (ext2_block_size)
addl $10, %ecx
movl %ecx, (ext2_block_shift)
cmpl $EXT2_BLOCK_SIZE, %eax
jne .has_ext2_filesystem_unsupported_block_size
# fill inode size
movl $128, %eax
@ -132,23 +130,38 @@ has_ext2_filesystem:
# reads block in to ext2_block_buffer
# eax: block number
ext2_read_block:
pushal
pushl %eax
pushl %ebx
pushw %cx
pushl %edx
pushw %di
# ecx := sectors_per_block := block_size / sector_size
movl (ext2_block_size), %ecx
shrl $SECTOR_SHIFT, %ecx
# NOTE: this assumes 1024 block size
# eax := (block * block_size) / sector_size := (eax << EXT2_BLOCK_SHIFT) >> SECTOR_SHIFT
xorl %edx, %edx
shll $EXT2_BLOCK_SHIFT, %eax
shrl $SECTOR_SHIFT, %eax
# ebx:eax := block * sectors_per_block + (ext2_partition_first_sector)
xorl %ebx, %ebx
mull %ecx
# ebx:eax := eax + (ext2_partition_first_sector)
movl (ext2_partition_first_sector + 4), %ebx
addl (ext2_partition_first_sector + 0), %eax
adcl (ext2_partition_first_sector + 4), %ebx
jnc .ext2_read_block_no_carry
incl %ebx
.ext2_read_block_no_carry:
# sectors per block
movw $(EXT2_BLOCK_SIZE / SECTOR_SIZE), %cx
movw $ext2_block_buffer, %di
movb (ext2_drive_number), %dl
call read_from_disk
popal
popw %di
popl %edx
popw %cx
popl %ebx
popl %eax
ret
@ -157,23 +170,15 @@ ext2_read_block:
ext2_read_block_group_descriptor:
pushal
# ebx := bgd_block_byte_offset := (s_first_data_block + 1) * block_size
# := (s_first_data_block + 1) << ext2_block_shift
movl (ext2_superblock_buffer + s_first_data_block), %ebx
incl %ebx
movb (ext2_block_shift), %cl
shll %cl, %ebx
# eax := bgd_byte_offset := 2048 + EXT2_BGD_SIZE * eax := (eax << EXT2_BGD_SHIFT) + 2048
shll $EXT2_BGD_SHIFT, %eax
addl $2048, %eax
# eax := bgd_byte_offset := bgd_block_byte_offset + EXT2_BGD_SIZE * block_group;
# := bgd_block_byte_offset + (block_group << EXT2_BGD_SHIFT)
movb $EXT2_BGD_SHIFT, %cl
shll %cl, %eax
addl %ebx, %eax
# eax: bgd_block := bgd_byte_offset / block_size
# ebx: bgd_offset := bgd_byte_offset % block_size
# eax: bgd_block := bgd_byte_offset / EXT2_BLOCK_SIZE
# ebx: bgd_offset := bgd_byte_offset % EXT2_BLOCK_SIZE
xorl %edx, %edx
divl (ext2_block_size)
movl $EXT2_BLOCK_SIZE, %ebx
divl %ebx
movl %edx, %ebx
call ext2_read_block
@ -199,19 +204,23 @@ ext2_read_inode:
# ebx := inode_index = (ino - 1) % s_inodes_per_group
xorl %edx, %edx
decl %eax
divl (ext2_superblock_buffer + s_inodes_per_group)
movl (ext2_superblock_buffer + s_inodes_per_group), %ebx
divl %ebx
movl %edx, %ebx
call ext2_read_block_group_descriptor
# eax := inode_table_block := (inode_index * inode_size) / block_size
# ebx := inode_table_offset := (inode_index * inode_size) % block_size
# eax := inode_table_block := (inode_index * inode_size) / EXT2_BLOCK_SIZE
# ebx := inode_table_offset := (inode_index * inode_size) % EXT2_BLOCK_SIZE
xorl %edx, %edx
movl %ebx, %eax
mull (ext2_inode_size)
divl (ext2_block_size)
movl (ext2_inode_size), %ebx
mull %ebx
movl $EXT2_BLOCK_SIZE, %ebx
divl %ebx
movl %edx, %ebx
# eax := filesystem_block := eax + bg_inode_table
# eax := file system block := eax + bg_inode_table
addl (ext2_block_group_descriptor_buffer + bg_inode_table), %eax
movb (ext2_drive_number), %dl
@ -246,17 +255,14 @@ ext2_data_block_index:
pushl %esi
pushl %edi
# ebx := max_data_blocks := (file_size + block_size - 1) / block_size
# := (i_size + ext2_block_size - 1) >> ext2_block_shift
# cl := ext2_block_shift
movl (ext2_inode_buffer + i_size), %ebx
addl (ext2_block_size), %ebx
decl %ebx
movb (ext2_block_shift), %cl
shrl %cl, %ebx
# calculate max data blocks
movl (ext2_inode_buffer + i_size), %ecx
addl (ext2_inode_size), %ecx
decl %ecx
shll $EXT2_BLOCK_SHIFT, %ecx
# verify data block is within bounds
cmpl %ebx, %eax
cmpl %ecx, %eax
jae .ext2_data_block_index_out_of_bounds
# check if this is direct block access
@ -264,26 +270,18 @@ ext2_data_block_index:
jb .ext2_data_block_index_direct
subl $12, %eax
# cl := indices_per_block_shift := ext2_block_shift - 2
# ebx := comp
subb $2, %cl
movl $1, %ebx
shll %cl, %ebx
# check if this is singly indirect block access
cmpl %ebx, %eax
cmpl $(EXT2_BLOCK_SIZE / 4), %eax
jb .ext2_data_block_index_singly_indirect
subl %ebx, %eax
shll %cl, %ebx
subl $(EXT2_BLOCK_SIZE / 4), %eax
# check if this is doubly indirect block access
cmpl %ebx, %eax
cmpl $((EXT2_BLOCK_SIZE / 4) * (EXT2_BLOCK_SIZE / 4)), %eax
jb .ext2_data_block_index_doubly_indirect
subl %ebx, %eax
shll %cl, %ebx
subl $((EXT2_BLOCK_SIZE / 4) * (EXT2_BLOCK_SIZE / 4)), %eax
# check if this is triply indirect block access
cmpl %ebx, %eax
cmpl $((EXT2_BLOCK_SIZE / 4) * (EXT2_BLOCK_SIZE / 4) * (EXT2_BLOCK_SIZE / 4)), %eax
jb .ext2_data_block_index_triply_indirect
# otherwise this is invalid access
@ -316,12 +314,9 @@ ext2_data_block_index:
# ebx := index
# cx := depth
.ext2_data_block_index_indirect:
# edx := cache index := (index & ~(block_size / 4 - 1)) | depth
# := (index & -(block_size >> 2)) | depth
movl (ext2_block_size), %edx
shrl $2, %edx
negl %edx
andl %ebx, %edx
# calculate cache index ((index & 0xFF) | depth)
movl %ebx, %edx
andl $(~(EXT2_BLOCK_SIZE / 4 - 1)), %edx
orw %cx, %dx
# check whether this block is already cached
@ -348,21 +343,20 @@ ext2_data_block_index:
jbe .ext2_data_block_index_no_shift
# cl := shift
movb (ext2_block_shift), %al
subb $2, %al
movb $(EXT2_BLOCK_SHIFT - 2), %al
decb %cl
mulb %cl
movb %al, %cl
# ebx := ebx >> shift
# ebx := ebx >> cl
shrl %cl, %ebx
.ext2_data_block_index_no_shift:
# edx := index of next block (ebx & (block_size / 4 - 1))
movl (ext2_block_size), %edx
shrl $2, %edx
decl %edx
andl %ebx, %edx
# edx := index of next block
movl %ebx, %eax
xorl %edx, %edx
movl $(EXT2_BLOCK_SIZE / 4), %ebx
divl %ebx
# eax := next block
movl $ext2_block_buffer, %esi
@ -377,7 +371,7 @@ ext2_data_block_index:
# cache last read block
movw $ext2_block_buffer, %si
movw $ext2_inode_indirect_buffer, %di
movw (ext2_block_size), %cx
movw $EXT2_BLOCK_SIZE, %cx
rep movsb
jmp .ext2_data_block_index_done
@ -396,10 +390,7 @@ ext2_data_block_index:
.ext2_data_block_index_indirect_cached:
movl $ext2_inode_indirect_buffer, %esi
movl (ext2_block_size), %edx
shrl $2, %edx
decl %edx
andl %edx, %ebx
andl $(EXT2_BLOCK_SIZE / 4 - 1), %ebx
movl (%esi, %ebx, 4), %eax
.ext2_data_block_index_done:
@ -419,7 +410,6 @@ ext2_data_block_index:
.global ext2_inode_read_bytes
ext2_inode_read_bytes:
pushal
pushl %ebp
movl %esp, %ebp
subl $8, %esp
@ -428,11 +418,11 @@ ext2_inode_read_bytes:
movl %eax, 0(%esp)
movl %ecx, 4(%esp)
# eax := first_byte / block_size
# edx := first_byte % block_size
# when edx == 0, no partial read needed
# check if eax % EXT2_BLOCK_SIZE != 0,
# then we need to read a partial block starting from an offset
xorl %edx, %edx
divl (ext2_block_size)
movl $EXT2_BLOCK_SIZE, %ebx
divl %ebx
testl %edx, %edx
jz .ext2_inode_read_bytes_no_partial_start
@ -441,7 +431,7 @@ ext2_inode_read_bytes:
call ext2_read_block
# ecx := byte count (min(block_size - edx, remaining_bytes))
movl (ext2_block_size), %ecx
movl $EXT2_BLOCK_SIZE, %ecx
subl %edx, %ecx
cmpl %ecx, 4(%esp)
cmovbl 4(%esp), %ecx
@ -455,7 +445,7 @@ ext2_inode_read_bytes:
addl %edx, %esi
# very dumb memcpy with 32 bit addresses
xorl %ebx, %ebx
movl $0, %ebx
.ext2_inode_read_bytes_memcpy_partial:
movb (%esi, %ebx), %al
movb %al, (%edi, %ebx)
@ -471,15 +461,14 @@ ext2_inode_read_bytes:
.ext2_inode_read_bytes_no_partial_start:
# eax := data block index (byte_start / block_size)
movl 0(%esp), %eax
movb (ext2_block_shift), %cl
shrl %cl, %eax
shrl $(EXT2_BLOCK_SHIFT), %eax
# get data block index and read block
call ext2_data_block_index
call ext2_read_block
# calculate bytes to copy (min(block_size, remaining_bytes))
movl (ext2_block_size), %ecx
movl $EXT2_BLOCK_SIZE, %ecx
cmpl %ecx, 4(%esp)
cmovbl 4(%esp), %ecx
@ -535,12 +524,11 @@ ext2_directory_find_inode:
cmpw $0xFF, %cx
ja .ext2_directory_find_inode_not_found
# ebx := max data blocks: ceil(i_size / block_size)
# ebx := max data blocks: ceil(i_size / EXT2_BLOCK_SIZE)
movl (ext2_inode_buffer + i_size), %ebx
addl (ext2_block_size), %ebx
addl $EXT2_BLOCK_SHIFT, %ebx
decl %ebx
movb (ext2_block_shift), %cl
shrl %cl, %ebx
shrl $EXT2_BLOCK_SHIFT, %ebx
jz .ext2_directory_find_inode_not_found
# 4(%esp) := current block
@ -587,9 +575,7 @@ ext2_directory_find_inode:
# go to next entry if this block contains one
addw 4(%si), %si
movw $ext2_block_buffer, %di
addw (ext2_block_size), %di
cmpw %di, %si
cmpw $(ext2_block_buffer + EXT2_BLOCK_SIZE), %si
jb .ext2_directory_find_inode_loop_entries
.ext2_directory_find_inode_next_block:
@ -598,7 +584,7 @@ ext2_directory_find_inode:
jb .ext2_directory_find_inode_block_read_loop
.ext2_directory_find_inode_not_found:
xorb %al, %al
movb $0, %al
jmp .ext2_directory_find_inode_done
.ext2_directory_find_inode_found:
@ -710,7 +696,7 @@ root_partition_does_not_fit_ext2_filesystem_msg:
root_partition_has_invalid_ext2_magic_msg:
.asciz "Root partition doesn't contain ext2 magic number"
root_partition_has_unsupported_ext2_block_size_msg:
.asciz "Root partition has unsupported ext2 block size (1 KiB, 2 KiB and 4 KiB are supported)"
.asciz "Root partition has unsupported ext2 block size (only 1024 supported)"
ext2_part_not_dir_msg:
.asciz "inode in root path is not directory"
@ -731,12 +717,12 @@ ext2_looking_for_msg:
.section .bss
.align SECTOR_SIZE
.align EXT2_BLOCK_SIZE
ext2_block_buffer:
.skip EXT2_MAX_BLOCK_SIZE
.skip EXT2_BLOCK_SIZE
ext2_inode_indirect_buffer:
.skip EXT2_MAX_BLOCK_SIZE
.skip EXT2_BLOCK_SIZE
ext2_inode_indirect_number:
.skip 4
@ -750,10 +736,6 @@ ext2_drive_number:
# NOTE: fits in 2 bytes
ext2_inode_size:
.skip 4
ext2_block_size:
.skip 4
ext2_block_shift:
.skip 4
ext2_superblock_buffer:
.skip EXT2_SUPERBLOCK_SIZE

View File

@ -57,7 +57,11 @@ vesa_scan_kernel_image:
# Find suitable video mode and save it in (vesa_target_mode)
vesa_find_video_mode:
pushal
pushw %ax
pushw %bx
pushw %cx
pushw %di
pushl %esi
pushl %ebp
movl %esp, %ebp
@ -83,7 +87,7 @@ vesa_find_video_mode:
# get vesa information
movw $0x4F00, %ax
movw $vesa_info_buffer, %di
pushl %ebp; int $0x10; popl %ebp # BOCHS doesn't seem to reserve ebp
int $0x10
cmpb $0x4F, %al; jne .vesa_unsupported
cmpb $0x00, %ah; jne .vesa_error
@ -95,7 +99,8 @@ vesa_find_video_mode:
cmpw $0x0200, (vesa_info_buffer + 0x04)
jb .vesa_unsupported_version
movl (vesa_info_buffer + 0x0E), %esi
movl $(vesa_info_buffer + 0x0E), %esi
movl (%esi), %esi
.vesa_find_video_mode_loop_modes:
cmpw $0xFFFF, (%esi)
je .vesa_find_video_mode_loop_modes_done
@ -104,7 +109,7 @@ vesa_find_video_mode:
movw $0x4F01, %ax
movw (%esi), %cx
movw $vesa_mode_info_buffer, %di
pushl %ebp; int $0x10; popl %ebp # BOCHS doesn't seem to reserve ebp
int $0x10
cmpb $0x4F, %al; jne .vesa_unsupported
cmpb $0x00, %ah; jne .vesa_error
@ -141,7 +146,11 @@ vesa_find_video_mode:
.vesa_find_video_mode_loop_modes_done:
leavel
popal
popl %esi
popw %di
popw %cx
popw %bx
popw %ax
ret
.vesa_unsupported:
@ -171,14 +180,14 @@ vesa_set_video_mode:
movw $0x4F02, %ax
orw $0x4000, %bx
pushl %ebp; int $0x10; popl %ebp # BOCHS doesn't seem to reserve ebp
int $0x10
jmp .set_video_done
.vesa_set_target_mode_generic:
movb $0x03, %al
movb $0x00, %ah
pushl %ebp; int $0x10; popl %ebp # BOCHS doesn't seem to reserve ebp
int $0x10
.set_video_done:
popw %bx

View File

@ -87,7 +87,7 @@ sudo partprobe $LOOP_DEV
PARTITION1=${LOOP_DEV}p1
PARTITION2=${LOOP_DEV}p2
sudo mkfs.ext2 -q $PARTITION2
sudo mkfs.ext2 -q -b 1024 $PARTITION2
sudo mkdir -p $MOUNT_DIR || { echo "Failed to create banan mount dir."; exit 1; }