OSDev.org

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

All times are UTC - 6 hours




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 2:11 am 
Offline
Member
Member
User avatar

Joined: Sun Jul 21, 2019 7:34 am
Posts: 293
Hey. I asked a similar question earlier, but never found an answer. Please help again.

I use GRUB as my bootloader. In the kernel file.asm I run VESA mode with the screen 800x600 8 bbp. The file itself looks like this:
Code:
bits 32
%define MULTIBOOT_MAGIC 0x1BADB002
%define MULTIBOOT_FLAGS (1<<0 | 1<<1 | 1<<2)

section .text
align 4
multiboot_header:
    dd MULTIBOOT_MAGIC
    dd MULTIBOOT_FLAGS
    dd -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS)
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 800 ; width
    dd 600 ; height
    dd 8 ; bbp

global start
extern kmain

start:
  cli
  mov esp, stack_space
  call kmain
  hlt

section .bss
resb 8192
stack_space:


Here's my kernel.c:
Code:
#include "kernel.h"

void kmain(void)
{
    memset((void*)0xFD000000, 0xFF0000, sizeof(0xFD000000));
    return;
}


The QEMU window changes in size, which means that VESA mode is enabled.
According to this article, the video memory address of QEMU is 0xFD000000.
Using
Code:
memset
I try to paint the whole screen red, but nothing comes out.
Please, help.


Last edited by mrjbom on Tue Jul 23, 2019 4:04 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 3:12 am 
Offline
Member
Member

Joined: Wed Mar 30, 2011 12:31 am
Posts: 676
According to what article? I will correct it.

QEMU does not use a fixed address for the framebuffer. Grub will pass the framebuffer address to you in the multiboot struct (and you can also locate it through PCI).

_________________
toaruos on github | toaruos.org | gitlab | twitter | bim - a text editor


Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 3:23 am 
Offline
Member
Member
User avatar

Joined: Sat Mar 31, 2012 3:07 am
Posts: 4591
Location: Chichester, UK
What do you suppose sizeof(0xFD000000) is?

So how many pixels are you setting?

(I can confirm that 0xFD000000 is the correct value for the address of the framebuffer in this case.)


Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 3:38 am 
Offline
Member
Member
User avatar

Joined: Mon Jan 15, 2018 2:27 pm
Posts: 201
Your memset is wrong. First, memset operates on bytes (at lest on logical level). So your color 0xFF0000 is truncated to byte 0x00.
Second, sizeof operator is used incorrectly. sizeof(0xFD000000) returns 4, which is the same as sizeof(int) So you would change just 4 bytes. You should calculate size of the framebuffer using fomula
Code:
width * height * bits_per_pixel / 8  // not always correct
or
Code:
height * pitch // this is correct way to do it
Where pitch is number of bytes per scanline (can be found in multiboot_info structure).
Next, 8 bit mode doesn't know about RGB, it uses palette instead. I think 32 bit color would be a better option.
Also assuming fixed framebuffer address (0xFD000000 in your case) is reaaaaly bad thing to do. Proper way here is to parse multiboot_info structure which is pointed to by ebx.


Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 3:46 am 
Offline
Member
Member
User avatar

Joined: Sun Jul 21, 2019 7:34 am
Posts: 293
Drawing In Protected Mode
klange wrote:
According to what article? I will correct it.


Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 5:07 am 
Offline
Member
Member
User avatar

Joined: Sun Jul 21, 2019 7:34 am
Posts: 293
klange wrote:
QEMU does not use a fixed address for the framebuffer. Grub will pass the framebuffer address to you in the multiboot struct (and you can also locate it through PCI).


I tried to do it, but it didn't work. I used the code for multiboot info from this site.

Complement of its kernel.asm up to this:
Code:
bits 32

%define MULTIBOOT_MAGIC 0x1BADB002
%define MULTIBOOT_FLAGS (1<<0 | 1<<1 | 1<<2)
%define KERNEL_BASE     0xFFFF800000000000

section .text
align 4
multiboot_header:
    dd MULTIBOOT_MAGIC
    dd MULTIBOOT_FLAGS
    dd -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS)
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 800 ; width
    dd 600 ; height
    dd 32 ; bbp

global start
extern kmain

start:
  cli
  mov esp, stack_space
  mov [multiboot_info_ptr - KERNEL_BASE], ebx
  call kmain
  hlt

section .bss
multiboot_info_ptr
resb 8192
stack_space:


kernel.c looks like this:
Code:
#include "kernel.h"

#define VESA_WIDTH 800
#define VESA_HEIGHT 600
#define VESA_BBP 32
#define VESA_SIZE VESA_WIDTH * VESA_HEIGHT * VESA_BBP / 8

void kmain(unsigned long magic, unsigned long addr)
{
    multiboot_info_t *mbi;
    mbi = (multiboot_info_t *) addr;
    memset((void*)mbi->framebuffer_addr, 0xFF0000, VESA_SIZE);
    return;
}


But I see only a black screen again. I suspect grub doesn't give me the address on the multiboot info. But I can't check it.


Last edited by mrjbom on Tue Jul 23, 2019 5:13 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 5:12 am 
Offline
Member
Member
User avatar

Joined: Sun Jul 21, 2019 7:34 am
Posts: 293
I tried to do this: memset((void*)0xFD000000, 0xFF0000, VESA_SIZE);
VESA_SIZE is calculated by this formula VESA_SIZE = VESA_WIDTH * VESA_HEIGHT * VESA_BBP / 8

iansjack wrote:
What do you suppose sizeof(0xFD000000) is?

So how many pixels are you setting?

(I can confirm that 0xFD000000 is the correct value for the address of the framebuffer in this case.)


Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 6:34 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
You never pushed the parameters for kmain before calling it. Since you have the magic number first and the multiboot pointer second you'd have to do push ebx then push eax and then do call kmain.


Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 7:32 am 
Offline
Member
Member
User avatar

Joined: Sun Jul 21, 2019 7:34 am
Posts: 293
MichaelPetch wrote:
You never pushed the parameters for kmain before calling it. Since you have the magic number first and the multiboot pointer second you'd have to do push ebx then push eax and then do call kmain.


I added the code kernel.asm, now it looks like this:
Code:
bits 32

%define MULTIBOOT_MAGIC 0x1BADB002
%define MULTIBOOT_FLAGS (1<<0 | 1<<1 | 1<<2)
%define KERNEL_BASE     0xFFFF800000000000

section .text
align 4
multiboot_header:
    dd MULTIBOOT_MAGIC
    dd MULTIBOOT_FLAGS
    dd -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS)
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 800 ; width
    dd 600 ; height
    dd 32 ; bbp

global start
extern kmain

start:
  cli
  mov esp, stack_space
  mov [multiboot_info_ptr - KERNEL_BASE], ebx
  push ebx
  push eax
  call kmain
  hlt

section .bss
multiboot_info_ptr
resb 8192
stack_space:


But it doesn't help, the screen is still black, not red. Apparently, the address on multiboot info on prematurely doesn't turn.


Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 8:56 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 671
Although this code falsely assumes the requested video mode of 800x600x32bpp is the one GRUB set, it should be enough to get you going:
Code:
bits 32

%define MULTIBOOT_MAGIC 0x1BADB002
%define MULTIBOOT_FLAGS (1<<0 | 1<<1 | 1<<2)

section .text
align 4
multiboot_header:
    dd MULTIBOOT_MAGIC
    dd MULTIBOOT_FLAGS
    dd -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS)
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 800 ; width
    dd 600 ; height
    dd 32 ; bbp

global start
extern kmain

start:
  cli
  mov esp, stack_space
  push ebx
  push eax
  call kmain
  hlt

section .bss
resb 8192
stack_space:

Code:
#include <stdint.h>
#include "multiboot.h"

void kmain(uint32_t magic, multiboot_info_t *mbi)
{
    (void) magic; /* Silence compiler warning since magic isn't used */
    volatile uint32_t *fb = (uint32_t *)((uint32_t) mbi->framebuffer_addr);
    uint32_t cell;

    for (cell = 0; cell < mbi->framebuffer_width * mbi->framebuffer_height; cell++)
        fb[cell] = 0x00ff0000;

    return;
}
The code above is not generic and assumes 32bpp (not 8 ). I leave it up to the reader to handle pitch and bits per pixels properly.


Last edited by MichaelPetch on Tue Jul 23, 2019 9:06 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Can't paint a pixel using VESA. How it works?
PostPosted: Tue Jul 23, 2019 9:04 am 
Offline
Member
Member
User avatar

Joined: Sun Jul 21, 2019 7:34 am
Posts: 293
MichaelPetch wrote:
Although this code falsely assumes the requested video mode of 800x600x32bpp is the one GRUB set, it should be enough to get you going



Perfectly. Thank you very much, you helped me very much.


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: Majestic-12 [Bot] and 56 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