How to get the linear framebuffer address using multiboot?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
amandude
Posts: 10
Joined: Wed Jul 07, 2021 7:18 pm

How to get the linear framebuffer address using multiboot?

Post by amandude »

I just got into VESA mode 1440 * 900 via multiboot 0.6.96, but I can't seem to access the linear framebuffer address to print pixels. I have tried getting the address from the multiboot header struct in my "main.c" file, but it keeps looping (glitching) when I try to access it. I have also tried finding the linear framebuffer address online for VESA mode 1440 * 900, but I can't seem to find a table for each mode that lists each framebuffer address for a specific mode.

Does anybody know the linear framebuffer address for VESA mode 1440 * 900, or does anybody have source code to properly get the linear framebuffer address from the multiboot header struct?

Here is what I have been following to get the linear framebuffer address from the multiboot header struct:

https://stackoverflow.com/questions/606 ... -vesa-mode

Thanks for all of your help! :D
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to get the linear framebuffer address using multiboo

Post by Octocontrabass »

amandude wrote:it keeps looping (glitching) when I try to access it.
Please explain what this means.

Can you show us your code?
amandude
Posts: 10
Joined: Wed Jul 07, 2021 7:18 pm

Re: How to get the linear framebuffer address using multiboo

Post by amandude »

This means it tries to change to VESA mode but then switches back and fourth rapidly between VESA mode and before boot. it scrolls text too before boot and then deletes it and scrolls again. Sorry if I am bad at explaining it :|



Here is my code:

c code:
void kernel_main(unsigned int* MultiBootHeaderStruct) {
unsigned int* framebuffer = (unsigned int*)MultiBootHeaderStruct[22];
framebuffer[100] = 0x7800;
}

assembly code (multiboot):
bits 32

dd 0x1BADB002
dd 0x04
dd -(0x1BADB002 + 0x04)

dd 0
dd 0
dd 0
dd 0
dd 0

dd 0
dd 1440
dd 900
dd 32

main.asm:

bits 32

section .text

global start
extern long_mode_start
EXTERN main
GLOBAL _Kernel_Start:function
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; Constant declaring base of Higher-half kernel
KERNEL_PAGE_TABLE equ (KERNEL_VIRTUAL_BASE >> 22) ; Constant declaring Page Table index in virtual memory


start:
mov esp, stack_top
call check_cpuid
call check_long_mode
call setup_page_tables
call enable_paging
lgdt [gdt64.pointer]
jmp gdt64.code_segment:long_mode_start

check_multiboot:
cmp eax, 0x36d76289
jne .no_multiboot
ret

.no_multiboot:
mov al, "M"
jmp error

check_cpuid:
pushfd
pop eax
mov ecx, eax
xor eax, 1 << 21
push eax
popfd
pushfd
pop eax
push ecx
popfd
cmp eax, ecx
je .no_cpuid
ret
.no_cpuid:
mov al, "C"
jmp error

check_long_mode:
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb .no_long_mode

mov eax, 0x80000001
cpuid
test edx, 1 << 29
jz .no_long_mode

ret
.no_long_mode:
mov al, "L"
jmp error

setup_page_tables:
mov eax, page_table_l3
or eax, 0b11 ; present, writable
mov [page_table_l4], eax

mov eax, page_table_l2
or eax, 0b11 ; present, writable
mov [page_table_l3], eax

mov ecx, 0 ; counter
.loop:

mov eax, 0x200000 ; 2MiB
mul ecx
or eax, 0b10000011 ; present, writable, huge page
mov [page_table_l2 + ecx * 8], eax

inc ecx ; increment counter
cmp ecx, 512 ; checks if the whole table is mapped
jne .loop ; if not, continue

ret


enable_paging:
; pass page table location to cpu
mov eax, page_table_l4
mov cr3, eax

; enable PAE
mov eax, cr4
or eax, 1 << 5
mov cr4, eax

; enable long mode
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr

; enable paging
mov eax, cr0
or eax, 1 << 31
mov cr0, eax

ret ; Perform Far jump to set CS.

error:
; print "ERR: X" where X is the error code
mov dword [0xb8000], 0x4f524f45
mov dword [0xb8004], 0x4f3a4f52
mov dword [0xb8008], 0x4f204f20
mov byte [0xb800a], al

section .bss
align 4096
page_table_l4:
resb 4096
page_table_l3:
resb 4096
page_table_l2:
resb 4096
stack_bottom:
resb 4096 * 4
stack_top:


section .rodata
gdt64:
dq 0 ; zero entry
.code_segment: equ $ - gdt64
dq (1 << 43) | (1 << 44) | (1 << 47) | (1 << 53) ; code segment
.pointer:
dw $ - gdt64 - 1 ; length
dq gdt64 ; address

main64.asm:

bits 64

section .text

global long_mode_start
extern kernel_main

long_mode_start:
call kernel_main
hlt


Thanks for the reply!
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: How to get the linear framebuffer address using multiboo

Post by Octocontrabass »

You're not passing the pointer to the multiboot structure to kernel_main. Assuming you're following the System V AMD64 psABI, you need to put it in RDI.

Also, please use code tags to format your code when you post it.
Post Reply