VBE from protected mode with vm86

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.
Andy1988
Member
Member
Posts: 50
Joined: Fri Aug 22, 2008 12:01 pm
Location: Germany - Aachen

VBE from protected mode with vm86

Post by Andy1988 »

Hello everybody,
I want to implement a small VBE driver which changes video modes and draws into framebuffer from protected mode.
For all the BIOS legacy stuff, I want to use the VM86 mode.

As far as I read howtos and sample code I already understand how this mode works and what I need to do to set it up.
What I don't get yet is, how I'm able to call INTO the BIOS. Calling out of the BIOS (at least from sight of the running realmode program) is easy. Run your INT as you would do in real mode and then emulate it in protected mode.

So, normally I have a DOS Program, load it, set up the VM86 Environment and let it run. As soon as an INT instruction, port I/O or stuff like that happens a GPF Exception occurs. I catch the exception, emulate the desired behaviour and return back into the execution of the DOS Code. So far, so good.

But what about the other direction? When I want to query all video modes from VBE in protected mode, it is my obligation to execute the BIOS code which is responsible for this. In realmode, you would execute an interrupt and the handler inside the BIOS is executed.
Now, with VM86, I somehow need to trap into the this handler of the BIOS by myself to run this code. How is this done? Do I need to look them up in the IVT from the BIOS and then modify the vm86 stack to jump there?
Also, let's assume I don't have a realmode program I want to run but only call the realmode BIOS routines from protected mode. What about this? Find the entrypoint of the desired interrupt handler in the IVT of the BIOS, modify the environment to land at this interrupt handler and then, after the handler executed and "ireted", I terminate this fake environment again?

Another question is, how does the BIOS code then configure the graphics adapter? Is it done with port I/O? I think so.
But which ports are accessed? I need to set up the iopriv bitmask somehow.

This is insane, just for switching video modes... :shock:

edit:
Yes, I know that there is a patched GRUB for this. I don't want to use it.
I could also switch back to unreal mode just after I got loaded from GRUB. I don't want to do this either.
I want to be able to control the video card whenever I want to. Not just directly after boot and then never again in the running software.
Also it looks kinda hacky to me if I need to change my startup code to change a video mode. There are computers without VGA and just a serial line. How should I handle this? One big ifdef to compile different code? Or perhaps parsing the whole kernel commandline to know wether I need to do the switch in such an early boot stage? No, thank you...
User avatar
Artlav
Member
Member
Posts: 178
Joined: Fri Aug 21, 2009 5:54 am
Location: Moscow, Russia
Contact:

Re: VBE from protected mode with vm86

Post by Artlav »

If i understood you right, there are many ways to do it.
For example, compose a small program - int X, int 99, and run it in VM, registers set for int X parameters. Then, when your VM monitor intercepts an int 99 command, it's time to exit.

You can directly set up the the call for VM - look up the vector in IVT, make a stack frame with return address pointing to something guaranteed to cause an exception, run and wait for that exception. Or, same set-up, but count irets instead, this way you can do it without any code generation. Once the iret matching original int is met, exit.

If you want a general call, it can be rm_int that does the last case running specified int, or a rm_exec, which runs 16 bit code supplied, or something else.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: VBE from protected mode with vm86

Post by Combuster »

Andy1988 wrote:But which ports are accessed? I need to set up the iopriv bitmask somehow.
In general, you don't know.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Andy1988
Member
Member
Posts: 50
Joined: Fri Aug 22, 2008 12:01 pm
Location: Germany - Aachen

Re: VBE from protected mode with vm86

Post by Andy1988 »

Artlav wrote:If i understood you right, there are many ways to do it.
For example, compose a small program - int X, int 99, and run it in VM, registers set for int X parameters. Then, when your VM monitor intercepts an int 99 command, it's time to exit.
This seems to be the easiest way.
Unfortunately I don't have a benefit from this. If the IOPL of the code is 3, then the IVT is ignored and the IDT used instead. If it is < 3 then a GPF is thrown. The first case is totally useless to me. In the latter case I need to look up the exception handler by hand again and modify my environment to return in the appropriate handler. Then, after an IRET, which also causes an GPF, I need to change the environment again to return at the instruction after the INT call.
Or am I missing something and there is an easier way?
Artlav wrote:You can directly set up the the call for VM - look up the vector in IVT, make a stack frame with return address pointing to something guaranteed to cause an exception, run and wait for that exception. Or, same set-up, but count irets instead, this way you can do it without any code generation. Once the iret matching original int is met, exit.
Which is what I need to do anyway if I use the first solution.
Artlav wrote:If you want a general call, it can be rm_int that does the last case running specified int, or a rm_exec, which runs 16 bit code supplied, or something else.
Yeah, something like that.
Combuster wrote:
Andy1988 wrote:But which ports are accessed? I need to set up the iopriv bitmask somehow.
In general, you don't know.
Great. So, try and error on a hand full of machines and some praying or full io privileges... :-/

x86, I love you! #-o

edit:
I mainly got my information from this howto: http://osdev.berlios.de/v86.html
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Re: VBE from protected mode with vm86

Post by Ready4Dis »

Well, there is always the Real mode emulator trick... basically use (or write) an x86 16-bit emulator that runs the code from pmode or long mode. It allows full preemptive multitasking, and will work from long mode (unlike v86). Also, the emulator can be part of the video driver itself rather than part of your kernel, so when you swap out the video driver, you don't have legacy stuff cluttering/taking up space in the kernel. Of course, it's a bit more work to get working properly, and a bit less documentation (especially for things that require timers, etc, you may have to update the BDA timer locations and such to emulate a timer or similar), but like I said, works from pmode and long mode, and can easily be interrupted without any ugly hacks in the kernel. You could drop back to real mode, which works, but then you can lose interrupts and add a lot of lag/delay during mode switches (although, honestly, not many people are doing a whole lot during the switch, and you can check to see if an interrupt flags are stored once you return and trigger them manually).

Those are pretty much the options without writing a video card specific driver. Chose your poison ;).
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: VBE from protected mode with vm86

Post by Gigasoft »

The interrupt redirection bitmap in the TSS allows you to control if a specific software interrupt should cause a GPF. But yeah, you need to simulate IRET and other trapped instructions.

The VGA ROM should be allowed to access any I/O port. You can assume that it doesn't access anything besides than the display device.
User avatar
Artlav
Member
Member
Posts: 178
Joined: Fri Aug 21, 2009 5:54 am
Location: Moscow, Russia
Contact:

Re: VBE from protected mode with vm86

Post by Artlav »

Ready4Dis wrote:Well, there is always the Real mode emulator trick... basically use (or write) an x86 16-bit emulator that runs the code from pmode or long mode.
It happens to be not so easy, as i had found out.
Running interrupts in a thru-IO 80186 emulator works nicely in Qemu, but even in Bochs it fails.
The reason being that the BIOS code is free to use Exx parts of the registers in itself, and writing real mode of x86 emulator is quite a few orders of magnitude harder than writing an 80186 emulator. So, it's a bad idea unless you have one already.
Andy1988 wrote:In the latter case I need to look up the exception handler by hand again and modify my environment to return in the appropriate handler. Then, after an IRET, which also causes an GPF, I need to change the environment again to return at the instruction after the INT call.
Or am I missing something and there is an easier way?
Yes, that's pretty much what you would have to do - emulate the trapped instructions. That's why it's called a v86 monitor.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: VBE from protected mode with vm86

Post by Owen »

Artlav wrote:
Ready4Dis wrote:Well, there is always the Real mode emulator trick... basically use (or write) an x86 16-bit emulator that runs the code from pmode or long mode.
It happens to be not so easy, as i had found out.
Running interrupts in a thru-IO 80186 emulator works nicely in Qemu, but even in Bochs it fails.
The reason being that the BIOS code is free to use Exx parts of the registers in itself, and writing real mode of x86 emulator is quite a few orders of magnitude harder than writing an 80186 emulator. So, it's a bad idea unless you have one already.
Go and download x86emu from Freedesktop.org. It's proven very useful in practice - I believe its even used to fire up x86 PCI video cards on non-x86 machines these days!
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: VBE from protected mode with vm86

Post by Brendan »

Hi,
Andy1988 wrote:
Combuster wrote:
Andy1988 wrote:But which ports are accessed? I need to set up the iopriv bitmask somehow.
In general, you don't know.
Great. So, try and error on a hand full of machines and some praying or full io privileges... :-/
You can get a list of I/O ports used by the video card from "VBE Function 0Ah - Return VBE Protected Mode Interface". For video cards that use memory mapped I/O this function will also tell you about the base address and size of the memory mapped I/O area.

Don't forget that nothing (except maybe common sense, but common sense isn't guaranteed) prevents the real mode VBE functions from switching to protected mode (so that they can access the card's memory mapped I/O area). Also, if the OS messes with anything that the video card relies on (including changing PCI device BARs, changing interrupt controller configuration that could be used by VBE for a vertical retrace IRQ, etc) then VBE could fail.

Finally, if the OS supports U/EFI, OpenFirmware, coreboot or whatever Intel's Moblin platform uses for firmware (either directly or via. something like GRUB2) then you can't assume the BIOS or VBE even exists (which means relying on VBE when the OS is running becomes a portability nightmare if you ever want to support "non-PC-BIOS" 80x86 systems now or in the future).

IMHO the "most sane" choice is to setup a video mode (and framebuffer) during boot (using "pre-boot environment" specific methods that can include "real mode code + VBE") and not allowing the video mode to be switched after boot without a native video driver. This avoids the need for messy compile-time options and/or having many different versions of the kernel that are all almost the same except for legacy video handling.

Ideally the OS will (eventually) have native video drivers; and IMHO (for a serious project) supporting any fallback method of video mode switching after boot (used when there's no native video driver) isn't worth the hassle - it's a short term gain (that causes long term pain).


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.
Andy1988
Member
Member
Posts: 50
Joined: Fri Aug 22, 2008 12:01 pm
Location: Germany - Aachen

Re: VBE from protected mode with vm86

Post by Andy1988 »

I'm just reading the x86emu code from X.Org to emulate this code.
It's very well written and as Owen stated portable.
To me it seems that this is the most painless way to use VBE.

This whole driver is going to be used in the kernel for a bootsplash and, much more important, a bigger screen for kernel messages and a kernel debugger. The whole logging infrastructure already is configurable during runtime. Wether you want text, VBE or whatever.

Later, this whole thing is going to be embedded in a real graphics driver later like X.org is doing it. So it can coexist with other or even no graphics device.
If you don't have graphics, you don't load a driver.
Problem solved :)

Thanks all!
I learned a lot.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: VBE from protected mode with vm86

Post by Owen »

Brendan wrote:Don't forget that nothing (except maybe common sense, but common sense isn't guaranteed) prevents the real mode VBE functions from switching to protected mode (so that they can access the card's memory mapped I/O area). Also, if the OS messes with anything that the video card relies on (including changing PCI device BARs, changing interrupt controller configuration that could be used by VBE for a vertical retrace IRQ, etc) then VBE could fail.
Fortunately, for as long as VBE has been used it has been expected to be used under v8086! First it was under DOS memory managers, then under OS v8086. Any VBE driver which did anything out of the capabilities of v8086 mode would work pretty much nowhere ;)
Andy1988
Member
Member
Posts: 50
Joined: Fri Aug 22, 2008 12:01 pm
Location: Germany - Aachen

Re: VBE from protected mode with vm86

Post by Andy1988 »

Yay! I just got the x86emu to do what I want. At least outside of my kernel.
There seems to be no documentation available. Only x.org code and libx86 which both use x86emu.

It's not very hard

Code: Select all

#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>

#include "x86emu.h"

char _1234[] = { 0xb8, 0x34, 0x12 };

char* memory;

void printk(const char *fmt, ...)
{
    va_list argptr;
    va_start(argptr, fmt);
    vfprintf(stdout, fmt, argptr);
    fflush(stdout);
    va_end(argptr);
}

//M defined in x86emu/regs.h
int main(int argc, char* argv[])
{
    memset(&M, 0, sizeof(M));
    memory = malloc(0x1000);
    M.mem_base = (unsigned long)memory;
    M.mem_size = 0x1000;
    
    memcpy(memory, _1234, sizeof(_1234));
    
    X86EMU_exec();
    
    printf("eax: %x", M.x86.gen.A.I32_reg.e_reg);
    
    return 0;
}
Result:

Code: Select all

mem_read: address 0x1000 out of range!
halt_sys: file sys.c, line 231
eax: 1234
The code just moves 0x1234 to eax.
Works :)

I'll try to map a BIOS into the memory and prepare a stack for executing my INT 10's.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: VBE from protected mode with vm86

Post by Combuster »

Brendan wrote:Hi,
Andy1988 wrote:But which ports are accessed? I need to set up the iopriv bitmask somehow.
Combuster wrote:In general, you don't know.
Andy1988 wrote:Great. So, try and error on a hand full of machines and some praying or full io privileges... :-/
You can get a list of I/O ports used by the video card from "VBE Function 0Ah - Return VBE Protected Mode Interface". For video cards that use memory mapped I/O this function will also tell you about the base address and size of the memory mapped I/O area.
That requires you to run the bios when you don't know which ports are going to be used (potential chicken-and-egg problem), and both the function and port list are optional. And wasn't there that rumour that the protected mode interface was broken in general?
Ideally the OS will (eventually) have native video drivers; and IMHO (for a serious project) supporting any fallback method of video mode switching after boot (used when there's no native video driver) isn't worth the hassle - it's a short term gain (that causes long term pain).
Never tried using a VGA driver as fallback?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
tom9876543
Member
Member
Posts: 170
Joined: Wed Jul 18, 2007 5:51 am

Re: VBE from protected mode with vm86

Post by tom9876543 »

I am no expert but IMHO trying to get a fully operating VBE graphics mode is a waste of time. Unfortunately you really need to write native drivers. You can look at the Linux / BSD source code to help you. Be careful if you decide to copy it!

Slightly off topic.....

What is the graphics mode Linux goes into when it boots up and you see all the text messages with a Penguin at the top???? That is probably the limits of what can be achieved with VBE. Does anyone know what the relevant source code file in Linux is?
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: VBE from protected mode with vm86

Post by Owen »

tom9876543 wrote:I am no expert but IMHO trying to get a fully operating VBE graphics mode is a waste of time. Unfortunately you really need to write native drivers. You can look at the Linux / BSD source code to help you. Be careful if you decide to copy it!
Native drivers for what?

Intel cards are documented. nVIDIA ones aren't. ATi ones kinda are.

For the last two, you should hopefully be able to get a clue from the Kernel Mode Setting code that's recently gone in now (rather than ferreting about with the XOrg drivers)
Post Reply