[Closed] Setting VESA/VBE Mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

[Closed] Setting VESA/VBE Mode

Post 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. :|
Last edited by Octacone on Mon Jul 17, 2017 5:38 am, edited 2 times in total.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Setting VESA/VBE Mode

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: Setting VESA/VBE Mode

Post 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.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Setting VESA/VBE Mode

Post 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?
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Antti
Member
Member
Posts: 923
Joined: Thu Jul 05, 2012 5:12 am
Location: Finland

Re: Setting VESA/VBE Mode

Post 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.
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: Setting VESA/VBE Mode

Post 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.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Setting VESA/VBE Mode

Post 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.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
dseller
Member
Member
Posts: 84
Joined: Thu Jul 03, 2014 5:18 am
Location: The Netherlands
Contact:

Re: Setting VESA/VBE Mode

Post 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.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Setting VESA/VBE Mode

Post 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.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
jeaye
Posts: 8
Joined: Tue May 24, 2016 6:48 pm
Libera.chat IRC: jeaye
Location: San Francisco
Contact:

Re: Setting VESA/VBE Mode

Post 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.
User avatar
BrightLight
Member
Member
Posts: 901
Joined: Sat Dec 27, 2014 9:11 am
Location: Maadi, Cairo, Egypt
Contact:

Re: Setting VESA/VBE Mode

Post 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.
You know your OS is advanced when you stop using the Intel programming guide as a reference.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Setting VESA/VBE Mode

Post 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
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
DeezRamChips
Member
Member
Posts: 132
Joined: Fri Apr 08, 2016 5:03 am
Location: atapio.cpp - why won't you work :(
Contact:

Re: Setting VESA/VBE Mode

Post 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
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: Setting VESA/VBE Mode

Post 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.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
DeezRamChips
Member
Member
Posts: 132
Joined: Fri Apr 08, 2016 5:03 am
Location: atapio.cpp - why won't you work :(
Contact:

Re: Setting VESA/VBE Mode

Post 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
Post Reply