219 lines
4.8 KiB
ArmAsm
219 lines
4.8 KiB
ArmAsm
.code16
|
|
.section .stage2
|
|
|
|
# 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
|
|
# 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:
|
|
pushal
|
|
|
|
pushl %ebp
|
|
movl %esp, %ebp
|
|
subl $6, %esp
|
|
|
|
# clear target mode and frame buffer
|
|
movw $0, (vesa_target_mode)
|
|
movl $0, (framebuffer + 0)
|
|
movl $0, (framebuffer + 4)
|
|
movl $0, (framebuffer + 8)
|
|
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
|
|
pushl %ebp; int $0x10; popl %ebp # BOCHS doesn't seem to reserve ebp
|
|
cmpb $0x4F, %al; jne .vesa_unsupported
|
|
cmpb $0x00, %ah; jne .vesa_error
|
|
|
|
# confirm that response starts with 'VESA'
|
|
cmpl $0x41534556, (vesa_info_buffer)
|
|
jne .vesa_error
|
|
|
|
# confirm that version is atleast 2.0
|
|
cmpw $0x0200, (vesa_info_buffer + 0x04)
|
|
jb .vesa_unsupported_version
|
|
|
|
movl (vesa_info_buffer + 0x0E), %esi
|
|
.vesa_find_video_mode_loop_modes:
|
|
cmpw $0xFFFF, (%esi)
|
|
je .vesa_find_video_mode_loop_modes_done
|
|
|
|
# get info of next 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
|
|
cmpb $0x4F, %al; jne .vesa_unsupported
|
|
cmpb $0x00, %ah; jne .vesa_error
|
|
|
|
# check whether in graphics mode
|
|
testb $0x10, (vesa_mode_info_buffer + 0)
|
|
jz .vesa_find_video_mode_next_mode
|
|
|
|
# compare mode's dimensions
|
|
movw -2(%ebp), %ax; cmpw %ax, (vesa_mode_info_buffer + 0x12)
|
|
jne .vesa_find_video_mode_next_mode
|
|
movw -4(%ebp), %ax; cmpw %ax, (vesa_mode_info_buffer + 0x14)
|
|
jne .vesa_find_video_mode_next_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)
|
|
movw (vesa_mode_info_buffer + 0x10), %ax
|
|
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
|
|
|
|
.vesa_find_video_mode_next_mode:
|
|
addl $2, %esi
|
|
jmp .vesa_find_video_mode_loop_modes
|
|
|
|
.vesa_find_video_mode_loop_modes_done:
|
|
leavel
|
|
popal
|
|
ret
|
|
|
|
.vesa_unsupported:
|
|
movw $vesa_unsupported_msg, %si
|
|
jmp print_and_halt
|
|
.vesa_unsupported_version:
|
|
movw $vesa_unsupported_version_msg, %si
|
|
jmp print_and_halt
|
|
.vesa_error:
|
|
movw $vesa_error_msg, %si
|
|
jmp print_and_halt
|
|
|
|
|
|
# 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
|
|
|
|
movw $0x4F02, %ax
|
|
orw $0x4000, %bx
|
|
pushl %ebp; int $0x10; popl %ebp # BOCHS doesn't seem to reserve ebp
|
|
|
|
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
|
|
|
|
.set_video_done:
|
|
popw %bx
|
|
popw %ax
|
|
ret
|
|
|
|
.section .data
|
|
|
|
vesa_error_msg:
|
|
.asciz "VESA error"
|
|
vesa_unsupported_msg:
|
|
.asciz "VESA unsupported"
|
|
vesa_unsupported_version_msg:
|
|
.asciz "VESA unsupported version"
|
|
vesa_success_msg:
|
|
.asciz "VESA success"
|
|
|
|
.section .bss
|
|
|
|
vesa_info_buffer:
|
|
.skip 512
|
|
|
|
vesa_mode_info_buffer:
|
|
.skip 256
|
|
|
|
vesa_target_mode:
|
|
.skip 2
|
|
|
|
.global framebuffer
|
|
.align 8
|
|
framebuffer:
|
|
.skip 4 # address
|
|
.skip 4 # pitch
|
|
.skip 4 # width
|
|
.skip 4 # height
|
|
.skip 1 # bpp
|
|
.skip 1 # type
|