Compare commits

..

3 Commits

Author SHA1 Message Date
Bananymous e4ed65b897 Kernel: Add framebuffer information to kernel image 2023-12-09 17:33:58 +02:00
Bananymous 75579f15d4 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.
2023-12-09 17:32:10 +02:00
Bananymous fbe75b6d63 Bootloader: Generalize framebuffer video mode search
Framebuffer size is now taken as arguments to vesa_find_video_mode
2023-12-09 16:48:04 +02:00
4 changed files with 110 additions and 28 deletions

View File

@ -60,8 +60,6 @@ stage2_main:
call get_memory_map
call read_user_command_line
call vesa_find_video_mode
call print_newline
movw $start_kernel_load_msg, %si
@ -84,7 +82,7 @@ stage2_main:
call elf_read_kernel_to_memory
call vesa_set_target_mode
call vesa_set_video_mode
cli

View File

@ -1,20 +1,72 @@
.set TARGET_WIDTH, 800
.set TARGET_HEIGHT, 600
.set TARGET_BPP, 32
.code16
.section .stage2
# Find suitable video mode
# 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: video mode number if found, 0 otherwise
.global vesa_find_video_mode
# ax: target width
# bx: target height
# 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
pushl %ebp
movl %esp, %ebp
subl $6, %esp
# clear target mode and frame buffer
movw $0, (vesa_target_mode)
movl $0, (framebuffer + 0)
@ -23,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
@ -57,21 +118,24 @@ vesa_find_video_mode:
jz .vesa_find_video_mode_next_mode
# compare mode's dimensions
cmpw $TARGET_WIDTH, (vesa_mode_info_buffer + 0x12)
movw -2(%ebp), %ax; cmpw %ax, (vesa_mode_info_buffer + 0x12)
jne .vesa_find_video_mode_next_mode
cmpw $TARGET_HEIGHT, (vesa_mode_info_buffer + 0x14)
movw -4(%ebp), %ax; cmpw %ax, (vesa_mode_info_buffer + 0x14)
jne .vesa_find_video_mode_next_mode
cmpb $TARGET_BPP, (vesa_mode_info_buffer + 0x19)
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)
movl $TARGET_WIDTH, (framebuffer + 8)
movl $TARGET_HEIGHT, (framebuffer + 12)
movb $TARGET_BPP, (framebuffer + 16)
movb $1, (framebuffer + 17)
movw %ax, (framebuffer + 4)
movb $1, (framebuffer + 17)
# 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)
movw %cx, (vesa_target_mode)
jmp .vesa_find_video_mode_loop_modes_done
@ -81,9 +145,11 @@ vesa_find_video_mode:
jmp .vesa_find_video_mode_loop_modes
.vesa_find_video_mode_loop_modes_done:
leavel
popl %esi
popw %di
popw %cx
popw %bx
popw %ax
ret
@ -98,13 +164,16 @@ 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

View File

@ -2,6 +2,10 @@
.set PG_READ_WRITE, 1<<1
.set PG_PAGE_SIZE, 1<<7
.set FB_WIDTH, 800
.set FB_HEIGHT, 600
.set FB_BPP, 32
#define KERNEL_OFFSET 0xFFFFFFFF80000000
#define V2P(vaddr) ((vaddr) - KERNEL_OFFSET)
@ -9,8 +13,8 @@
# multiboot2 header
.section .multiboot, "aw"
multiboot2_start:
.align 8
multiboot2_start:
.long 0xE85250D6
.long 0
.long multiboot2_end - multiboot2_start
@ -21,9 +25,9 @@ multiboot2_start:
.short 5
.short 0
.long 20
.long 800
.long 600
.long 32
.long FB_WIDTH
.long FB_HEIGHT
.long FB_BPP
# legacy start
.align 8
@ -38,6 +42,16 @@ multiboot2_start:
.long 8
multiboot2_end:
.section .bananboot, "aw"
.align 8
bananboot_start:
.long 0xBABAB007
.long -(0xBABAB007 + FB_WIDTH + FB_HEIGHT + FB_BPP)
.long FB_WIDTH
.long FB_HEIGHT
.long FB_BPP
bananboot_end:
.section .bss, "aw", @nobits
# Create stack
.global g_boot_stack_bottom

View File

@ -11,6 +11,7 @@ SECTIONS
{
g_kernel_execute_start = .;
*(.multiboot)
*(.bananboot)
*(.text.*)
}
.userspace ALIGN(4K) : AT(ADDR(.userspace) - KERNEL_OFFSET)