Page 1 of 7

[Closed] Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 5:49 am
by Octacone
As the title suggests I need a way to set some high resolution VES/VBE mode.

After my bootloader topic I decided to use GRUB2 as my bootloader.
Then we (yes two of us guys) implemented GDT, IDT, ISR, IRQ, Protected Mode, Shell, Basic VGA Driver, Drawing, some other C function and types etc...

At this moment, we have 320x200 VGA with 256 (64) colors. That is not really enough.
We decided that we want High Resolution VBE/VESA mode. Our goal is to achieve resolutions like 1024x768, 1360x768, 1920x1080.

Now we have no idea how to do that. After reading all those articles and tutorials, searching this forum for code... Nothing showed up.
I even tried porting already made VESA drivers, but without any luck.

I've also read that since we are using GRUB2 we can ask GRUB to set video mode for us?

Another important note it that we can directly write to BIOS using inportb and outportb functions. Can we set video mode by using them from our C code or we need some extra assembly functions?

Using protected mode makes this a bit difficult right?
Also there is something called V8086 monitor that is really hard to write but it can use BIOS functions that are not usable with protected mode on?

I would really appreciate some working code for setting graphics mode to VESA with some custom high resolutions or defined ones like 0x1018h.

Asking for makes me feel like a beggar, but that is the only way. :|

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 6:50 am
by Brendan
Hi,
thehardcoreOS wrote:I've also read that since we are using GRUB2 we can ask GRUB to set video mode for us?
It can (but more on that later).
thehardcoreOS wrote:Another important note it that we can directly write to BIOS using inportb and outportb functions. Can we set video mode by using them from our C code or we need some extra assembly functions?

Using protected mode makes this a bit difficult right?
That's a native video driver (which is possible), but means that you need a different driver for most different video cards and ends up being a lot of work.
thehardcoreOS wrote:Also there is something called V8086 monitor that is really hard to write but it can use BIOS functions that are not usable with protected mode on?
You can use V8086 (or software emulation); but that's extra work that is useless for modern (UEFI) computers so it's typically not worth bothering with.

There are 2 parts to this problem - finding a video mode that actually works (that the OS itself, and the video card, and the monitor all support); and setting that video mode.

For finding a video mode I'd:
  • get a list of all video modes that the video card supports (from UEFI, from VBE, or from native driver)
  • remove anything the OS doesn't support
  • remove anything the monitor doesn't support (based on EDID information)
  • give each video mode a score (representing things like if it's the monitor's native resolution, if it'll gobble too much RAM, if it will look ugly, how much it matches user's preferences if any, etc)
  • select the video mode with the best score
For setting a video mode, there are 2 options:
  • Use a native video driver (and write one for each video card). This probably isn't very practical; but allows you to support multiple monitors, multiple video cards, etc, and allows you to change video modes after boot without much hassle.
  • Use the firmware (VBE for BIOS, GOP or UGA for UEFI, etc). This is far more practical; but BIOS/VBE doesn't support multiple monitors or video cards properly and is painful for switching video modes after boot; and UEFI may or may not support multiple monitors or video cards properly (depends on whether there's appropriate UEFI drivers, etc) and can't be used at all for switching video modes after boot.
You mostly want to support both options. Essentially; use a native video driver if one exists, and use firmware as a "fallback" (for when you have no native video driver). In this case, for the "no driver fallback" it's not really worth bothering with the hassle of trying to support video mode switching after boot (partly because it's something that the user doesn't care about most of the time anyway).

Now... GRUB can set the video mode for you during boot (if the right "GRUB modules" are installed, etc); but it won't do it properly (e.g. doesn't really know what your software supports, doesn't check if the monitor supports the video mode, etc). Because of this, to get the best results the end user needs to configure GRUB (more end user hassle, more chance of user mis-configuring). It also can't work properly on something like a "live CD" (where it's impossible to configure GRUB to work for all the different computers the CD might be booted on). Finally, GRUB (multi-boot) has no support for multi-monitor or multiple video cards (even when you're booting on a UEFI system that has full support for this).

Basically; GRUB is the easiest form of "use firmware (indirectly) to setup video mode during boot", but it's also the worst option (for end user hassle), the worst option (for reliability), and the worst option (for features - e.g. multiple monitors, etc). ;)


Cheers,

Brendan

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 6:52 am
by BrightLight
If you're using GRUB2, the easiest way to do this is indeed requesting a video mode from GRUB. You can't request a specific mode number, but instead you pass the width, height and bits per pixel and GRUB will do the dirty work for you. Anyway, starting with VESA 2.0, no video mode numbers are standard and you should never depend on them.

inportb() and outportb() write to different hardware, not to the BIOS. The BIOS really is just a software that provides basic drivers for you hardware. Setting high resolution modes with port I/O will be very different for each graphics card, and nobody wants to write a driver for every single graphics card they'd like to support.

v8086 is indeed a solution, but it won't work on many real hardware, nor will it work in x86_64. Most real BIOSes switch to protected mode to access high memory, and that crosses the limits of v8086.

Read this section and this section of the multiboot specification. They explain how to request video modes, and then get information of the video mode.

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 7:24 am
by Octacone
omarrx024 wrote:If you're using GRUB2, the easiest way to do this is indeed requesting a video mode from GRUB. You can't request a specific mode number, but instead you pass the width, height and bits per pixel and GRUB will do the dirty work for you. Anyway, starting with VESA 2.0, no video mode numbers are standard and you should never depend on them.

inportb() and outportb() write to different hardware, not to the BIOS. The BIOS really is just a software that provides basic drivers for you hardware. Setting high resolution modes with port I/O will be very different for each graphics card, and nobody wants to write a driver for every single graphics card they'd like to support.

v8086 is indeed a solution, but it won't work on many real hardware, nor will it work in x86_64. Most real BIOSes switch to protected mode to access high memory, and that crosses the limits of v8086.

Read this section and this section of the multiboot specification. They explain how to request video modes, and then get information of the video mode.
Nice to hear that GRUB can do all that. I just really wanted to do a quick switch to VESA so we can code the s*it out of our GUI compositor.
Thanks for answering, now I need to study those links and see what I can get out of them. Btw are multiboot definitions inside asm defined by default or I need to define them my self like for e.g vbe_mode_info dd 0?

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 7:42 am
by Antti
The most annoying detail is here in this paragraph:
https://www.gnu.org/software/grub/manual/multiboot/multiboot.html wrote: 3.1.4 The graphics fields of Multiboot header

All of the graphics fields are enabled by flag bit 2. They specify the preferred graphics mode. Note that that is only a recommended mode by the OS image. If the mode exists, the boot loader should set it, when the user doesn't specify a mode explicitly. Otherwise, the boot loader should fall back to a similar mode, if available.
A similar mode? How to prioritize what is important and what is not? Sometimes color depth is far more important than resolution, for example.

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 7:44 am
by BrightLight
thehardcoreOS wrote:Nice to hear that GRUB can do all that. I just really wanted to do a quick switch to VESA so we can code the s*it out of our GUI compositor.
Thanks for answering, now I need to study those links and see what I can get out of them. Btw are multiboot definitions inside asm defined by default or I need to define them my self like for e.g vbe_mode_info dd 0?
I don't understand your question. GRUB passes the multiboot information in EBX. What you need to do it preserve EBX and pass it to your kernel. Your kernel should have a multiboot structure, and you use the value that was in EBX as a pointer to the multiboot structure. Then you can access the VBE fields.

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 7:53 am
by Octacone
omarrx024 wrote:
thehardcoreOS wrote:Nice to hear that GRUB can do all that. I just really wanted to do a quick switch to VESA so we can code the s*it out of our GUI compositor.
Thanks for answering, now I need to study those links and see what I can get out of them. Btw are multiboot definitions inside asm defined by default or I need to define them my self like for e.g vbe_mode_info dd 0?
I don't understand your question. GRUB passes the multiboot information in EBX. What you need to do it preserve EBX and pass it to your kernel. Your kernel should have a multiboot structure, and you use the value that was in EBX as a pointer to the multiboot structure. Then you can access the VBE fields.
Good point, my kernel does not have any multiboot structures. There is just a main function used for initialization of other system components.

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 7:58 am
by dseller
I tried the GRUB method too, but for me it wasn't really clear where the LFB address was (I don't think it is passed through the multiboot structure).

So therefore, I wrote some code to temporarily switch back to real mode, detect video modes and switch to the video mode I want (and storing the info block), and switching back to protected mode again.

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 8:16 am
by Octacone
dseller wrote:I tried the GRUB method too, but for me it wasn't really clear where the LFB address was (I don't think it is passed through the multiboot structure).

So therefore, I wrote some code to temporarily switch back to real mode, detect video modes and switch to the video mode I want (and storing the info block), and switching back to protected mode again.
Maybe you weren't returning the right value.

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 4:40 pm
by jeaye
There was a forum thread here http://forum.osdev.org/viewtopic.php?f=2&t=30186 which gives some good information on VESA; it's better than what's on the wiki, if I remember correctly. Unfortunately, it hasn't yet made it up onto the wiki; I pinged the author about it a few weeks ago and haven't heard back.

I'd imagine a number of people want to get into higher resolution + fancy graphics before they dig further into the meat of the OS, just for the instant gratification which is so uncommon in osdev. Unfortunately, a lot of the existing documentation for VESA work assumes quite a bit about what's been done so far and there aren't many documents explaining how to fit VESA into something like Bare Bones or Meaty Skeleton.

Re: Setting VESA/VBE Mode

Posted: Wed Jul 13, 2016 5:16 pm
by BrightLight
jeaye wrote:There was a forum thread here http://forum.osdev.org/viewtopic.php?f=2&t=30186 which gives some good information on VESA; it's better than what's on the wiki, if I remember correctly. Unfortunately, it hasn't yet made it up onto the wiki; I pinged the author about it a few weeks ago and haven't heard back.
I've completely forgotten I've even written that guide to VESA, and I never noticed your reply. Sorry about that! :oops:
EDIT: I've put it on the Wiki.

Re: Setting VESA/VBE Mode

Posted: Thu Jul 14, 2016 4:03 pm
by Octacone
Update:
I downloaded and included multiboot header file.

kernel_main(multiboot_info_t *mbit)
{
...
}

Now how do I set mbit.width and mbit.height mbi.mod_type mbi.depth?
I can not do that directly because compiler throws errors.
Is there any special assembly related code I need to do before that?

Update 2: I just discovered that you can set multiboot flags inside assembly and that they co-respond with those declared inside my C file.
Since I am using NASM I can not use stuff like .long and .set and I need to use equ and dd but I can not compiler that.

Update 3: I set all the flags for my graphics mode and trust me nothing happens:

Code: Select all

section         .text
        align 4
    dd MAGIC
    dd FLAGS
    dd CHECKSUM
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 1360
    dd 768
    dd 32

Re: Setting VESA/VBE Mode

Posted: Fri Jul 15, 2016 5:08 am
by DeezRamChips
thehardcoreOS wrote:Update:
I downloaded and included multiboot header file.

kernel_main(multiboot_info_t *mbit)
{
...
}

Now how do I set mbit.width and mbit.height mbi.mod_type mbi.depth?
I can not do that directly because compiler throws errors.
Is there any special assembly related code I need to do before that?

Update 2: I just discovered that you can set multiboot flags inside assembly and that they co-respond with those declared inside my C file.
Since I am using NASM I can not use stuff like .long and .set and I need to use equ and dd but I can not compiler that.

Update 3: I set all the flags for my graphics mode and trust me nothing happens:

Code: Select all

section         .text
        align 4
    dd MAGIC
    dd FLAGS
    dd CHECKSUM
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 1360
    dd 768
    dd 32
Exaclty the same problem !
i'm sure you use grub legacy do you ?
You need grub 2 or a patched version of grub legacy

Re: Setting VESA/VBE Mode

Posted: Fri Jul 15, 2016 5:36 am
by Octacone
Brendan wrote:Hi,
thehardcoreOS wrote:I've also read that since we are using GRUB2 we can ask GRUB to set video mode for us?
It can (but more on that later).
thehardcoreOS wrote:Another important note it that we can directly write to BIOS using inportb and outportb functions. Can we set video mode by using them from our C code or we need some extra assembly functions?

Using protected mode makes this a bit difficult right?
That's a native video driver (which is possible), but means that you need a different driver for most different video cards and ends up being a lot of work.
thehardcoreOS wrote:Also there is something called V8086 monitor that is really hard to write but it can use BIOS functions that are not usable with protected mode on?

You can use V8086 (or software emulation); but that's extra work that is useless for modern (UEFI) computers so it's typically not worth bothering with.

There are 2 parts to this problem - finding a video mode that actually works (that the OS itself, and the video card, and the monitor all support); and setting that video mode.

For finding a video mode I'd:
  • get a list of all video modes that the video card supports (from UEFI, from VBE, or from native driver)
  • remove anything the OS doesn't support
  • remove anything the monitor doesn't support (based on EDID information)
  • give each video mode a score (representing things like if it's the monitor's native resolution, if it'll gobble too much RAM, if it will look ugly, how much it matches user's preferences if any, etc)
  • select the video mode with the best score
For setting a video mode, there are 2 options:
  • Use a native video driver (and write one for each video card). This probably isn't very practical; but allows you to support multiple monitors, multiple video cards, etc, and allows you to change video modes after boot without much hassle.
  • Use the firmware (VBE for BIOS, GOP or UGA for UEFI, etc). This is far more practical; but BIOS/VBE doesn't support multiple monitors or video cards properly and is painful for switching video modes after boot; and UEFI may or may not support multiple monitors or video cards properly (depends on whether there's appropriate UEFI drivers, etc) and can't be used at all for switching video modes after boot.
You mostly want to support both options. Essentially; use a native video driver if one exists, and use firmware as a "fallback" (for when you have no native video driver). In this case, for the "no driver fallback" it's not really worth bothering with the hassle of trying to support video mode switching after boot (partly because it's something that the user doesn't care about most of the time anyway).

Now... GRUB can set the video mode for you during boot (if the right "GRUB modules" are installed, etc); but it won't do it properly (e.g. doesn't really know what your software supports, doesn't check if the monitor supports the video mode, etc). Because of this, to get the best results the end user needs to configure GRUB (more end user hassle, more chance of user mis-configuring). It also can't work properly on something like a "live CD" (where it's impossible to configure GRUB to work for all the different computers the CD might be booted on). Finally, GRUB (multi-boot) has no support for multi-monitor or multiple video cards (even when you're booting on a UEFI system that has full support for this).

Basically; GRUB is the easiest form of "use firmware (indirectly) to setup video mode during boot", but it's also the worst option (for end user hassle), the worst option (for reliability), and the worst option (for features - e.g. multiple monitors, etc). ;)


Cheers,

Brendan
Oh, this is a nice long article. I think that we won't be coding anything special at this moment. We just want to set high resolution VESA mode and use that. GRUB is our only option at this moment. We don't care for multiple monitors or graphics cards. This is just a private learning project and we just want to get VESA to work so we can hardcode our GUI compositor. Writing native graphics card drivers is almost impossible since there is no any documentation
on that topic. VESA + GRUB2 is our best bet since it supports high resolutions. Also I am using qemu with -kernel for my virtual machine and I already have my set vbe via grub code ready but nothing happens on boot, resolution stays the same.

Re: Setting VESA/VBE Mode

Posted: Fri Jul 15, 2016 6:17 am
by DeezRamChips
DeezRamChips wrote:
thehardcoreOS wrote:Update:
I downloaded and included multiboot header file.

kernel_main(multiboot_info_t *mbit)
{
...
}

Now how do I set mbit.width and mbit.height mbi.mod_type mbi.depth?
I can not do that directly because compiler throws errors.
Is there any special assembly related code I need to do before that?

Update 2: I just discovered that you can set multiboot flags inside assembly and that they co-respond with those declared inside my C file.
Since I am using NASM I can not use stuff like .long and .set and I need to use equ and dd but I can not compiler that.

Update 3: I set all the flags for my graphics mode and trust me nothing happens:

Code: Select all

section         .text
        align 4
    dd MAGIC
    dd FLAGS
    dd CHECKSUM
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 0
    dd 1360
    dd 768
    dd 32
Exaclty the same problem !
i'm sure you use grub legacy do you ?
You need grub 2 or a patched version of grub legacy
And add that to your grub.cfg file:

Code: Select all

insmod vbe
insmod vga