From 9ac3f48fcb709f4b58d666f36a46766655ab9a77 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 20 Apr 2024 17:57:16 +0300 Subject: [PATCH] Bootloader: Implement better memset and memcpy for 32 bit addresses --- bootloader/bios/CMakeLists.txt | 1 + bootloader/bios/boot.S | 12 ++-- bootloader/bios/common.S | 3 + bootloader/bios/elf.S | 22 +----- bootloader/bios/ext2.S | 20 +----- bootloader/bios/utils.S | 123 +++++++++++++++++++++++++++++++++ 6 files changed, 138 insertions(+), 43 deletions(-) create mode 100644 bootloader/bios/common.S diff --git a/bootloader/bios/CMakeLists.txt b/bootloader/bios/CMakeLists.txt index 1270569f99..a23e707cb1 100644 --- a/bootloader/bios/CMakeLists.txt +++ b/bootloader/bios/CMakeLists.txt @@ -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) diff --git a/bootloader/bios/boot.S b/bootloader/bios/boot.S index 583f71c684..5a318c68ca 100644 --- a/bootloader/bios/boot.S +++ b/bootloader/bios/boot.S @@ -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 diff --git a/bootloader/bios/common.S b/bootloader/bios/common.S new file mode 100644 index 0000000000..d295481d7d --- /dev/null +++ b/bootloader/bios/common.S @@ -0,0 +1,3 @@ +.set GDT_CODE16, 0x08 +.set GDT_DATA32, 0x10 +.set GDT_CODE32, 0x18 diff --git a/bootloader/bios/elf.S b/bootloader/bios/elf.S index e1d2d2c2c0..f925a98269 100644 --- a/bootloader/bios/elf.S +++ b/bootloader/bios/elf.S @@ -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 diff --git a/bootloader/bios/ext2.S b/bootloader/bios/ext2.S index edbcdfa300..cdc0317e46 100644 --- a/bootloader/bios/ext2.S +++ b/bootloader/bios/ext2.S @@ -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) diff --git a/bootloader/bios/utils.S b/bootloader/bios/utils.S index 95f3024901..369a2d3bdf 100644 --- a/bootloader/bios/utils.S +++ b/bootloader/bios/utils.S @@ -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