Page 1 of 3
I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 4:44 pm
by Caffeine
Hi, I can't seem to get my VGA driver to work. The problem is that the program seems to be hanging (see attached screenshot) when initializeVga() is called:
vga.c:
Code: Select all
#include "../Kernel/system.h"
#include "vga.h"
unsigned char *VGA;
unsigned short offset;
extern void enableVideoMode();
extern void disableVideoMode();
void initializeVGA() {
enableVideoMode();
*VGA = (unsigned char*)0xA0000;
}
void plotPixle(int x, int y, char color) {
offset = (y << 8) + (y << 6) + x;
VGA[offset] = color;
}
void test() {
for (int y = 3; y < 180; y++) { for (int i = 0; i < 319; i++) { offset = (y << 8) + (y << 6) + i; VGA[offset] = 1; } }
}
vga.asm:
Code: Select all
global enableVideoMode
global disableVideoMode
enableVideoMode:
mov ah, 0x00
mov al, 0x13
int 0x10
disableVideoMode:
mov ah, 0x00
mov al, 0x03
int 0x10
I am using qemu to emulate:
Code: Select all
qemu-system-i386 -cdrom Binaries/caffieneOS.iso
Sorry if the answerer is very obvious. I am not sure what to do here. I have been following this guide:
http://web.archive.org/web/201402180128 ... ac/vga.htm I found on the VGA recourses page.
Re: I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 5:05 pm
by klange
You are trying to call BIOS interrupts, but I would guess you're in protected mode. That doesn't make a lick of sense.
Re: I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 5:37 pm
by Caffeine
klange wrote:You are trying to call BIOS interrupts, but I would guess you're in protected mode. That doesn't make a lick of sense.
Thank you for pointing that out for me. Sorry for the beginner mistake.
How should I be implementing a VGA driver if I am in protected mode?
Re: I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 5:47 pm
by klange
You have a few options with various tradeoffs.
1. Don't. Let your bootloader configure a framebuffer for you. A bootloader like Grub will do this with the right config options; if you are writing your own loader, you just do what you were trying to do here before you jump to protected mode (and don't forget to pass some information on the video mode).
2. Write drivers for display devices. This is, of course, quite time-consuming and complicated and most display devices are poorly documented.
3. Use one of a few methods to call the BIOS APIs from protected mode: v8086 mode (won't work in long mode), return to real mode temporarily (flaky), or provide an emulator to run BIOS code and pass through io instructions (none of these options will work on EFI)
Re: I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 6:28 pm
by Caffeine
klange wrote:You have a few options with various tradeoffs.
1. Don't. Let your bootloader configure a framebuffer for you. A bootloader like Grub will do this with the right config options; if you are writing your own loader, you just do what you were trying to do here before you jump to protected mode (and don't forget to pass some information on the video mode).
2. Write drivers for display devices. This is, of course, quite time-consuming and complicated and most display devices are poorly documented.
3. Use one of a few methods to call the BIOS APIs from protected mode: v8086 mode (won't work in long mode), return to real mode temporarily (flaky), or provide an emulator to run BIOS code and pass through io instructions (none of these options will work on EFI)
How would I configure GRUB to do this?
Re: I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 7:07 pm
by alexfru
Caffeine wrote:
Code: Select all
unsigned char *VGA;
...
*VGA = (unsigned char*)0xA0000;
So, VGA starts out as NULL (unless that's also somehow broken in your build).
Then *VGA dereferences it.
Re: I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 7:19 pm
by klange
You can tell Grub you want to have a framebuffer at boot through
the 'graphics' fields in a multiboot1 header or the
framebuffer request tag in multiboot2, or more flexibly by setting the
gfxpayload variable in Grub after loading your kernel, immediately before booting. Use
set gfxpayload=keep to maintain the resolution set if Grub was running in graphical mode, otherwise you can pass WIDTHxHEIGHT or WIDTHxHEIGHTxBPP (eg 1024x768 or 1440x900x32) and Grub will make an effort to set that mode if possible. You can also set it to
text to get VGA text mode instead.
alexfru wrote:So, VGA starts out as NULL (unless that's also somehow broken in your build).
Then *VGA dereferences it.
Didn't even notice that issue...
Re: I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 9:21 pm
by Caffeine
klange wrote:You can tell Grub you want to have a framebuffer at boot through
the 'graphics' fields in a multiboot1 header or the
framebuffer request tag in multiboot2, or more flexibly by setting the
gfxpayload variable in Grub after loading your kernel, immediately before booting. Use
set gfxpayload=keep to maintain the resolution set if Grub was running in graphical mode, otherwise you can pass WIDTHxHEIGHT or WIDTHxHEIGHTxBPP (eg 1024x768 or 1440x900x32) and Grub will make an effort to set that mode if possible. You can also set it to
text to get VGA text mode instead.
alexfru wrote:So, VGA starts out as NULL (unless that's also somehow broken in your build).
Then *VGA dereferences it.
Didn't even notice that issue...
How do I implement the graphics in the multiboot header?
Re: I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 9:21 pm
by Caffeine
alexfru wrote:Caffeine wrote:
Code: Select all
unsigned char *VGA;
...
*VGA = (unsigned char*)0xA0000;
So, VGA starts out as NULL (unless that's also somehow broken in your build).
Then *VGA dereferences it.
Thanks for pointing this out, I'll fix this right now.
Re: I can't get my VGA driver to work
Posted: Thu Jan 20, 2022 11:18 pm
by Octocontrabass
Caffeine wrote:How do I implement the graphics in the multiboot header?
That depends on which version of Multiboot you're using.
If you're using
the first version of Multiboot, you need to set bit 2 of the flags, set mode_type to 0, and pick a reasonable default width, height, and depth. Many example Multiboot headers don't include anything after checksum, so you might need to add the missing fields to your Multiboot header.
If you're using
Multiboot2, you need to add a framebuffer tag to your Multiboot2 header. Make sure your tags are 8-byte aligned: the framebuffer tag is 20 bytes long, so you must tell your assembler to align the following tag or it won't work.
(Once your Multiboot header is set up for a graphics mode, you can choose a different graphics mode by setting gfxpayload in your GRUB configuration. This way, you don't need to compile a different kernel for each screen resolution!)
Re: I can't get my VGA driver to work
Posted: Fri Jan 21, 2022 12:12 am
by klange
Re: I can't get my VGA driver to work
Posted: Fri Jan 21, 2022 12:30 pm
by Caffeine
This worked! Video mode is enabled now! But I'm still not able to put a pixel on the screen. Here is my code:
Code: Select all
void plotPixle(int x, int y, unsigned char color) {
unsigned char* location = (unsigned char*)0xA0000 + (320 * y + x);
*location = color;
}
It has just been displaying a black screen.
Re: I can't get my VGA driver to work
Posted: Fri Jan 21, 2022 12:36 pm
by Octocontrabass
The framebuffer address is not 0xA0000. You need to get the framebuffer address from the Multiboot information structure.
Also, the framebuffer is probably not 8bpp. You need to get the bit depth from the Multiboot information structure too.
Re: I can't get my VGA driver to work
Posted: Fri Jan 21, 2022 3:34 pm
by Caffeine
Octocontrabass wrote:The framebuffer address is not 0xA0000. You need to get the framebuffer address from the Multiboot information structure.
Also, the framebuffer is probably not 8bpp. You need to get the bit depth from the Multiboot information structure too.
How do I get the framebuffer address and bit depth from the Multiboot information structure? I have been looking at the documentation for multiboot and can't figure it out.
Re: I can't get my VGA driver to work
Posted: Fri Jan 21, 2022 5:17 pm
by Octocontrabass
The Multiboot specifications include example code. Which part do you not understand?