From abc69fa3d57b4a3250abbfaccc7263f38d9eab05 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 9 Dec 2023 17:32:10 +0200 Subject: [PATCH] Bootloader: Search framebuffer information from kernel memory Framebuffer information is no longer hard coded into bootloader. Kernel can define framebuffer info structure in its memory which is used for finding proper video mode. --- bootloader/bios/boot.S | 7 +-- bootloader/bios/framebuffer.S | 103 ++++++++++++++++++++++++++-------- 2 files changed, 82 insertions(+), 28 deletions(-) diff --git a/bootloader/bios/boot.S b/bootloader/bios/boot.S index 196f206b..399311c4 100644 --- a/bootloader/bios/boot.S +++ b/bootloader/bios/boot.S @@ -59,11 +59,6 @@ stage2_main: call get_memory_map call read_user_command_line - - movw $800, %ax - movw $600, %bx - movb $32, %cl - call vesa_find_video_mode call print_newline @@ -87,7 +82,7 @@ stage2_main: call elf_read_kernel_to_memory - call vesa_set_target_mode + call vesa_set_video_mode cli diff --git a/bootloader/bios/framebuffer.S b/bootloader/bios/framebuffer.S index f4598774..980db770 100644 --- a/bootloader/bios/framebuffer.S +++ b/bootloader/bios/framebuffer.S @@ -1,14 +1,65 @@ .code16 .section .stage2 -# Find suitable video mode (argument registers not saved) +# kernel framebuffer information format +# .align 8 +# .long 0xBABAB007 +# .long -(0xBABAB007 + width + height + bpp) +# .long width (2 bytes used, 4 bytes for ease of calculation) +# .long height (2 bytes used, 4 bytes for ease of calculation) +# .long bpp (1 bytes used, 4 bytes for ease of calculation) + +# scan memory 0x100000 -> 0x200000 for framebuffer information +# return: # ax: target width # bx: target height -# cl: target bpp -# return: -# ax: video mode number if found, 0 otherwise -.global vesa_find_video_mode +# cx: target bpp +vesa_scan_kernel_image: + pushl %edx + pushl %esi + + movl $0x100000, %esi + + .vesa_scan_kernel_image_loop: + # check magic + cmpl $0xBABAB007, (%esi) + jne .vesa_scan_kernel_image_next_addr + + # check checksum + movl 0x00(%esi), %edx + addl 0x04(%esi), %edx + addl 0x08(%esi), %edx + addl 0x0C(%esi), %edx + addl 0x10(%esi), %edx + testl %edx, %edx + jnz .vesa_scan_kernel_image_next_addr + + # set return registers + movw 0x08(%esi), %ax + movw 0x0C(%esi), %bx + movw 0x10(%esi), %cx + jmp .vesa_scan_kernel_image_done + + .vesa_scan_kernel_image_next_addr: + addl $8, %esi + cmpl $0x200000, %esi + jb .vesa_scan_kernel_image_loop + + # zero out return registers + xorw %ax, %ax + xorw %bx, %bx + xorw %cx, %cx + + .vesa_scan_kernel_image_done: + popl %esi + popl %edx + ret + +# Find suitable video mode and save it in (vesa_target_mode) vesa_find_video_mode: + pushw %ax + pushw %bx + pushw %cx pushw %di pushl %esi @@ -16,13 +67,6 @@ vesa_find_video_mode: movl %esp, %ebp subl $6, %esp - # save arguments in stack - movw %ax, -2(%ebp) - movw %bx, -4(%ebp) - - andw $0xFF, %cx - movw %cx, -6(%ebp) - # clear target mode and frame buffer movw $0, (vesa_target_mode) movl $0, (framebuffer + 0) @@ -31,6 +75,15 @@ vesa_find_video_mode: movl $0, (framebuffer + 12) movw $0, (framebuffer + 16) + call vesa_scan_kernel_image + testw %ax, %ax + jz .vesa_find_video_mode_loop_modes_done + + # save arguments in stack + movw %ax, -2(%ebp) + movw %bx, -4(%ebp) + movw %cx, -6(%ebp) + # get vesa information movw $0x4F00, %ax movw $vesa_info_buffer, %di @@ -72,18 +125,18 @@ vesa_find_video_mode: movb -6(%ebp), %al; cmpb %al, (vesa_mode_info_buffer + 0x19) jne .vesa_find_video_mode_next_mode + # set address, pitch, type movl (vesa_mode_info_buffer + 0x28), %esi - movl %esi, (framebuffer + 0) + movl %esi, (framebuffer + 0) movw (vesa_mode_info_buffer + 0x10), %ax - movw %ax, (framebuffer + 4) + movw %ax, (framebuffer + 4) + movb $1, (framebuffer + 17) - xorl %eax, %eax + # set width, height, bpp movw -2(%ebp), %ax; movw %ax, (framebuffer + 8) movw -4(%ebp), %ax; movw %ax, (framebuffer + 12) movw -6(%ebp), %ax; movb %al, (framebuffer + 16) - movb $1, (framebuffer + 17) - movw %cx, (vesa_target_mode) jmp .vesa_find_video_mode_loop_modes_done @@ -95,6 +148,9 @@ vesa_find_video_mode: leavel popl %esi popw %di + popw %cx + popw %bx + popw %ax ret .vesa_unsupported: @@ -108,16 +164,19 @@ vesa_find_video_mode: jmp print_and_halt -# set mode found from vesa_find_video_mode. if no mode -# was found, set it to 80x25 text mode to clear the screen. -.global vesa_set_target_mode -vesa_set_target_mode: +# scan for video mode in kernel memory and set the correct one. +# when video mode is not found or does not exists, +# set it to 80x25 text mode to clear the screen. +.global vesa_set_video_mode +vesa_set_video_mode: pushw %ax pushw %bx + call vesa_find_video_mode + movw (vesa_target_mode), %bx testw %bx, %bx - jz .vesa_set_target_mode_generic + jz .vesa_set_target_mode_generic movw $0x4F02, %ax orw $0x4000, %bx