Bootloader: Implement better memset and memcpy for 32 bit addresses

This commit is contained in:
Bananymous 2024-04-20 17:57:16 +03:00
parent 0e405755ad
commit 9ac3f48fcb
6 changed files with 138 additions and 43 deletions

View File

@ -15,5 +15,6 @@ set(BOOTLOADER_SOURCES
)
add_executable(bootloader ${BOOTLOADER_SOURCES})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
target_link_options(bootloader PRIVATE LINKER:-T,${CMAKE_CURRENT_SOURCE_DIR}/linker.ld)
target_link_options(bootloader PRIVATE -nostdlib)

View File

@ -1,3 +1,5 @@
.include "common.S"
.code16
#########################################
@ -103,12 +105,12 @@ stage2_main:
movl %edx, %cr0
# jump to protected mode
ljmpl $0x18, $protected_mode
ljmpl $GDT_CODE32, $protected_mode
.code32
protected_mode:
# setup protected mode segments
movw $0x10, %dx
movw $GDT_DATA32, %dx
movw %dx, %ds
movw %dx, %es
movw %dx, %fs
@ -127,15 +129,15 @@ enter_unreal_mode:
movl %cr0, %eax
orb $1, %al
movl %eax, %cr0
ljmpl $0x8, $.enter_unreal_mode_pmode
ljmpl $GDT_CODE16, $.enter_unreal_mode_pmode
.enter_unreal_mode_pmode:
movw $0x10, %bx
movw $GDT_DATA32, %bx
movw %bx, %ds
andb $0xFE, %al
movl %eax, %cr0
ljmpl $0x0, $.enter_unreal_mode_unreal
ljmpl $0x00, $.enter_unreal_mode_unreal
.enter_unreal_mode_unreal:
popw %ds

3
bootloader/bios/common.S Normal file
View File

@ -0,0 +1,3 @@
.set GDT_CODE16, 0x08
.set GDT_DATA32, 0x10
.set GDT_CODE32, 0x18

View File

@ -113,24 +113,6 @@ elf_validate_file_header:
movw $elf_validate_file_header_not_executable_msg, %si
jmp print_and_halt
# sets memory to zero
# edi: start address
# ecx: byte count
# on return
# edi: start address + byte count
# ecx: 0
elf_memset_zero:
test %ecx, %ecx
jz .elf_memset_zero_done
.elf_memset_zero_loop:
movb $0, (%edi)
incl %edi
decl %ecx
jnz .elf_memset_zero_loop
.elf_memset_zero_done:
ret
# reads memory specified by 32 bit elf_program_header to memory
elf_read_program_header32_to_memory:
pushal
@ -144,7 +126,7 @@ elf_read_program_header32_to_memory:
addl %ebx, %edi
movl (elf_program_header + p32_memsz), %ecx
subl %ebx, %ecx
call elf_memset_zero
xorb %al, %al; call memset32
# read file specified in program header to memory
movl (elf_program_header + p32_offset), %eax
@ -171,7 +153,7 @@ elf_read_program_header64_to_memory:
addl %ebx, %edi
movl (elf_program_header + p64_memsz), %ecx
subl %ebx, %ecx
call elf_memset_zero
xorb %al, %al; call memset32
# read file specified in program header to memory
movl (elf_program_header + p64_offset), %eax

View File

@ -454,15 +454,7 @@ ext2_inode_read_bytes:
movl $ext2_block_buffer, %esi
addl %edx, %esi
# very dumb memcpy with 32 bit addresses
xorl %ebx, %ebx
.ext2_inode_read_bytes_memcpy_partial:
movb (%esi, %ebx), %al
movb %al, (%edi, %ebx)
incl %ebx
decl %ecx
jnz .ext2_inode_read_bytes_memcpy_partial
addl %ebx, %edi
call memcpy32
# check if all sectors are read
cmpl $0, 4(%esp)
@ -487,16 +479,8 @@ ext2_inode_read_bytes:
addl %ecx, 0(%esp)
subl %ecx, 4(%esp)
# very dumb memcpy with 32 bit addresses
movl $ext2_block_buffer, %esi
movl $0, %ebx
.ext2_inode_read_bytes_memcpy:
movb (%esi, %ebx), %al
movb %al, (%edi, %ebx)
incl %ebx
decl %ecx
jnz .ext2_inode_read_bytes_memcpy
addl %ebx, %edi
call memcpy32
# read next block if more sectors remaining
cmpl $0, 4(%esp)

View File

@ -1,3 +1,5 @@
.include "common.S"
.set SCREEN_WIDTH, 80
.set SCREEN_HEIGHT, 25
@ -273,6 +275,127 @@ isprint:
movb $0, %al
ret
# memset with 32 bit registers
# edi: destination address
# ecx: bytes count
# al: value to set
# return:
# edi: destination address + bytes count
# ecx: 0
# other: preserved
.global memset32
memset32:
testl %ecx, %ecx
jz .memset32_done
pushf; cli
pushw %es
pushl %eax
pushl %ebx
pushl %edx
movl %cr0, %ebx
orb $1, %bl
movl %ebx, %cr0
ljmpl $GDT_CODE32, $.memset32_pmode32
.code32
.memset32_pmode32:
movw $GDT_DATA32, %dx
movw %dx, %es
movl %ecx, %edx
andl $3, %ecx
rep stosb %es:(%edi)
movl %edx, %ecx
shrl $2, %ecx
movb %al, %ah
movw %ax, %dx
shll $16, %eax
movw %dx, %ax
rep stosl %es:(%edi)
ljmpl $GDT_CODE16, $.memset32_pmode16
.code16
.memset32_pmode16:
andb $0xFE, %bl
movl %ebx, %cr0
ljmpl $0x00, $.memset32_rmode16
.memset32_rmode16:
popl %edx
popl %ebx
popl %eax
popw %es
popf
.memset32_done:
ret
# memcpy with 32 bit registers
# esi: source address
# edi: destination address
# ecx: bytes count
# return:
# esi: source address + bytes count
# edi: destination address + bytes count
# ecx: 0
# other: preserved
.global memcpy32
memcpy32:
testl %ecx, %ecx
jz .memcpy32_done
pushf; cli
pushw %ds
pushw %es
pushl %ebx
pushl %edx
movl %cr0, %ebx
orb $1, %bl
movl %ebx, %cr0
ljmpl $GDT_CODE32, $.memcpy32_pmode32
.code32
.memcpy32_pmode32:
movw $GDT_DATA32, %dx
movw %dx, %ds
movw %dx, %es
movl %ecx, %edx
andl $3, %ecx
rep movsb %ds:(%esi), %es:(%edi)
movl %edx, %ecx
shrl $2, %ecx
rep movsl %ds:(%esi), %es:(%edi)
ljmpl $GDT_CODE16, $.memcpy32_pmode16
.code16
.memcpy32_pmode16:
andb $0xFE, %bl
movl %ebx, %cr0
ljmpl $0x00, $.memcpy32_rmode16
.memcpy32_rmode16:
popl %edx
popl %ebx
popw %es
popw %ds
popf
.memcpy32_done:
ret
.section .bss
# enough for base 2 printing