OSDev.org

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

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Problem parsing Multiboot2 struct
PostPosted: Sat Jun 04, 2022 2:42 am 
Offline

Joined: Sat Jun 04, 2022 1:29 am
Posts: 3
Following the wiki and tutorials I've successfully managed to boot my kernel and print using BIOS in long mode, however now I want to use a GOP framebuffer. I'm stuck trying to draw anything.
This is how my multiboot_header looks like:
Code:
section .multiboot_header
align 8
header_start:
    dd 0xe85250d6                ; magic
    dd 0
    dd header_end - header_start

    dd 0x100000000 - (0xe85250d6 + 0 + (header_end - header_start)) ; checksum

    ; framebuffer
    dw 5
    dw 0
    dd 20
    dd 640
    dd 480
    dd 32


    dw 0    ; end tag
    dw 0   ; flags
    dd 8    ; required
header_end:

This works, as the QEMU window resizes to 640x480.
Since I'm using long mode, I pass rbx to rdi before calling the kernel function:
Code:
global long_mode_start
section .text
bits 64
long_mode_start:
    mov ax, 0
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov rdi, rbx
    extern kernel_main
    call kernel_main
    hlt


And this is how I try to parse the struct, adapting a minimal version from the Multiboot2 specification example (I also dropped in multiboot2.h) and using a method from the wiki to draw a pixel:
Code:
#include <stdint.h>
#include "multiboot2.h"

extern "C" void kernel_main(unsigned long mbi_addr) {
    auto addr = mbi_addr;
    for (auto tag = (struct multiboot_tag *) ((uint8_t *) addr + 8);
         tag->type != MULTIBOOT_TAG_TYPE_END;
         tag = (struct multiboot_tag *) ((multiboot_uint8_t *) tag + ((tag->size + 7) & ~7))) {

        switch (tag->type) {
            case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: {
                auto *tagfb = (struct multiboot_tag_framebuffer *) tag;
                auto *fb = (multiboot_uint64_t *) (unsigned long) tagfb->common.framebuffer_addr;
                *((uint32_t *) (fb + 4 * tagfb->common.framebuffer_pitch * 100 + 4 * 100)) = 0xFFFFFFFF;
                break;
            }
        }
    }
}


The pixel isn't drawn and QEMU restarts after a while. Please help

EDIT: After going back to BIOS output and trying to just parse the multiboot header, the problem seems to occur when updating the tag value in the for loop. It enters the loop once and then triple faults.


Top
 Profile  
 
 Post subject: Re: Problem parsing Multiboot2 struct
PostPosted: Mon Jun 06, 2022 2:30 am 
Offline
Member
Member

Joined: Mon Jul 05, 2021 6:57 pm
Posts: 118
Is it possible your ebx value has been lost (overwritten) before you jump to long mode?

(You really should just attach a debugger and single-step through. You're almost certainly going to have to do that at a later stage anyway, may as well get used to it now.)

Edit: also, what do you mean by this?
Quote:
and print using BIOS in long mode

You can't use the BIOS in long mode.


Top
 Profile  
 
 Post subject: Re: Problem parsing Multiboot2 struct
PostPosted: Mon Jun 06, 2022 3:29 am 
Offline

Joined: Sat Jun 04, 2022 1:29 am
Posts: 3
davmac314 wrote:
Is it possible your ebx value has been lost (overwritten) before you jump to long mode?

(You really should just attach a debugger and single-step through. You're almost certainly going to have to do that at a later stage anyway, may as well get used to it now.)

I'm not touching ebx anywhere in the boot process, is there something else that could affect it?
I'll try to attach a debugger and go from there. I thought that since I managed to print text, drawing a few pixels would be easy :P

Quote:
You can't use the BIOS in long mode.

I got a little confused. I am not using the BIOS I was just printing to 0xB8000.


Top
 Profile  
 
 Post subject: Re: Problem parsing Multiboot2 struct
PostPosted: Mon Jun 06, 2022 3:51 am 
Offline
Member
Member

Joined: Mon Jul 05, 2021 6:57 pm
Posts: 118
Quote:
I'm not touching ebx anywhere in the boot process, is there something else that could affect it?


I mean generally not, but one thought I just had: are you sure the framebuffer, and also the multiboot information structure, are mapped into memory? I.e. how have you set up the paging for long mode?


Top
 Profile  
 
 Post subject: Re: Problem parsing Multiboot2 struct
PostPosted: Mon Jun 06, 2022 3:59 am 
Offline
Member
Member

Joined: Mon Feb 02, 2015 7:11 pm
Posts: 898
spyder23 wrote:
Code:
                auto *fb = (multiboot_uint64_t *) (unsigned long) tagfb->common.framebuffer_addr;
                *((uint32_t *) (fb + 4 * tagfb->common.framebuffer_pitch * 100 + 4 * 100)) = 0xFFFFFFFF;
The pixel isn't drawn and QEMU restarts after a while. Please help


1) I am not sure what a "multiboot_uint64_t" is, but if this is a uint64_t, it means you are doing your framebuffer calculations using 8 bytes entities. It's probably better to use uintptr_t (or a uint8_t*) for calculations to avoid such problems. This could explain the crash / not seeing the pixel. Also do not multiple the pitch by 4! The size of pixels is already taken into account in the pitch.
Code:
auto fb = (uintptr_t)tagfb->common.framebuffer_addr;
auto pixel = (uint32_t*)(fb + tagfb->common.framebuffer_pitch * 100 + 4 * 100);
*pixel = 0xFFFFFFFF;

2) Are you sure the framebuffer is 32 bits? - This probably would not explain the crash.

_________________
https://github.com/kiznit/rainbow-os


Last edited by kzinti on Mon Jun 06, 2022 10:14 am, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: Problem parsing Multiboot2 struct
PostPosted: Mon Jun 06, 2022 8:29 am 
Offline

Joined: Sat Jun 04, 2022 1:29 am
Posts: 3
davmac314 wrote:
Quote:
I'm not touching ebx anywhere in the boot process, is there something else that could affect it?


I mean generally not, but one thought I just had: are you sure the framebuffer, and also the multiboot information structure, are mapped into memory? I.e. how have you set up the paging for long mode?

Even though I went through the code several times, this magically made me see the issues.

1. I forgot to loop when setting up identity paging
2. I didn't have KEEP for the multiboot_header in the linker file
3. ebx was actually changed somehow, so I moved it into rdi at the very beginning instead of right before calling kernel_main
4. The tags themselves were not aligned properly (I was getting unsupported tag 0x8)

I can now parse the multiboot information struct without triple faulting so I guess the problem in the title is solved.
I still triple fault when trying to write to the framebuffer but that's probably because it's not in the first 2MB that I have mapped. I'll continue without it for now and set up IDT & serial and try to understand what I'm doing without just blindly following tutorials.

I appreciate both of you for your help.


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot], SemrushBot [Bot] and 70 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