OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 2:57 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Access UEFI gop framebuffer in longmode
PostPosted: Sun May 01, 2022 6:04 pm 
Offline

Joined: Sun May 01, 2022 5:40 pm
Posts: 2
I have bootstraped my kernel in longmode.
I am using multiboot version 1 with grub and I enabled the video flag.
I added the page where the framebuffer is to the page tables.
I passed the multiboot struct address to my C kernel.

From there I am trying to write to the framebuffer address but my kernel panics in qemu.
Also when I print the framebuffer address in gdb it says it cannot access the memory.
Code:
(gdb) print fb
$2 = 0xfd000000 <error: Cannot access memory at address 0xfd000000>


The code that I use to add the framebuffer page tables is:
Code:
setup_framebuffer_page_tables:
        /* Get the multiboot struct address */
        movl %ebx, %edx

        /*
        Offset to the framebuffer member. The offset of the framebuffer member is
        actually 84 and it size is 64 bits, but since we are currently in protected
        mode, the address cannot be bigger than 32 bits.
        */
        add $88, %edx
        movl (%edx), %edx

        /* L4 */
        movl %edx, %ecx
        shr $30, %ecx
        and $0b111111111, %ecx

        movl $page_table_l3_framebuffer, %eax
        orl $0b11, %eax
        movl %eax, page_table_l4(, %ecx, 8)

        /* L3 */
        movl %edx, %ecx
        shr $21, %ecx
        and $0b111111111, %ecx

        movl $page_table_l2_framebuffer, %eax
        orl $0b11, %eax
        movl %eax, page_table_l3_framebuffer(, %ecx, 8)

        /* Huge pages of size 2 MiBs */
        movl $0, %ecx
.loop2:

        movl $0x200000, %eax
        mul %ecx

        /* present, writable, hugepage */
        orl $0b10000011, %eax
        movl %eax, page_table_l2_framebuffer(, %ecx, 8)

        inc %ecx
        cmp $512, %ecx
        jne .loop2

        ret

I debugged the code and it seemed liked its adding the pages correctly, but I am not sure if I should also do something more, like edit the gdt64.

Essentially what I want is to have a working console as soon as possible in long mode.


Top
 Profile  
 
 Post subject: Re: Access UEFI gop framebuffer in longmode
PostPosted: Sun May 01, 2022 8:22 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
vtimofei wrote:
The offset of the framebuffer member is actually 84 and it size is 64 bits, but since we are currently in protected mode, the address cannot be bigger than 32 bits.

The Multiboot specification is correct, the offset of the framebuffer member truly is 88. The x86 architecture is little-endian, which means if you read 32 bits starting at offset 88 you will read bits 0-31 of the framebuffer member. You can read bits 32-63 at offset 92.

How does being in 32-bit mode stop you from doing the 64-bit math necessary to build your page tables? You're not going to access the framebuffer in protected mode, so it doesn't matter how many bits are in its address. (And if you did want to access it in protected mode, you just have to pick a new virtual address. PAE page tables allow all physical addresses to be mapped.)

Level 4 of the page tables is indexed by bits 39-47 of the virtual address. It looks like you're trying to use bits 30-31 instead...

You can use "info mem" and "info tlb" in the QEMU monitor to check your page tables. Make sure you use both! Some page table problems will only be visible in one and not the other.


Top
 Profile  
 
 Post subject: Re: Access UEFI gop framebuffer in longmode
PostPosted: Mon May 02, 2022 8:01 am 
Offline

Joined: Sun May 01, 2022 5:40 pm
Posts: 2
Octocontrabass wrote:
Level 4 of the page tables is indexed by bits 39-47 of the virtual address. It looks like you're trying to use bits 30-31 instead...

You are right, my paging setup for the framebuffer location was incorrect.

The qemu console, and the commands `info mem` and `info tlb` helped a ton thanks.

Posting the working code below:
Code:
setup_framebuffer_page_tables:
        /* Get the multiboot struct address */
        movl %ebx, %edx

        add $88, %edx
        movl (%edx), %edx

        /* L3 */
        movl %edx, %ecx
        shr $30, %ecx
        and $0b111111111, %ecx

        and $0xC0000000, %edx /* We will start mapping from this address */

        movl $page_table_l2_framebuffer, %eax
        orl $0b11, %eax
        movl %eax, page_table_l3(, %ecx, 8)

        /* Huge pages of size 2 MiBs */
        movl $0, %ecx
.loop2:

        movl $0x200000, %eax
        imul %ecx, %eax
        orl %edx, %eax

        /* present, writable, hugepage */
        orl $0b10000011, %eax
        movl %eax, page_table_l2_framebuffer(, %ecx, 8)

        inc %ecx
        cmp $512, %ecx
        jne .loop2

        ret


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 61 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group