VBE from protected mode with vm86
VBE from protected mode with vm86
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...
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...
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...
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...
Re: VBE from protected mode with vm86
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.
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.
- Combuster
- 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
In general, you don't know.Andy1988 wrote:But which ports are accessed? I need to set up the iopriv bitmask somehow.
Re: VBE from protected mode with vm86
This seems to be the easiest way.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.
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?
Which is what I need to do anyway if I use the first solution.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.
Yeah, something like that.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.
Great. So, try and error on a hand full of machines and some praying or full io privileges... :-/Combuster wrote:In general, you don't know.Andy1988 wrote:But which ports are accessed? I need to set up the iopriv bitmask somehow.
x86, I love you!
edit:
I mainly got my information from this howto: http://osdev.berlios.de/v86.html
Re: VBE from protected mode with vm86
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 .
Those are pretty much the options without writing a video card specific driver. Chose your poison .
Re: VBE from protected mode with vm86
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.
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.
Re: VBE from protected mode with vm86
It happens to be not so easy, as i had found out.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.
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.
Yes, that's pretty much what you would have to do - emulate the trapped instructions. That's why it's called a v86 monitor.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?
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: VBE from protected mode with vm86
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!Artlav wrote:It happens to be not so easy, as i had found out.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.
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.
Re: VBE from protected mode with vm86
Hi,
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
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.Andy1988 wrote:Great. So, try and error on a hand full of machines and some praying or full io privileges... :-/Combuster wrote:In general, you don't know.Andy1988 wrote:But which ports are accessed? I need to set up the iopriv bitmask somehow.
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.
Re: VBE from protected mode with vm86
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.
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.
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: VBE from protected mode with vm86
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 nowhereBrendan 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.
Re: VBE from protected mode with vm86
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
Result:
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.
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;
}
Code: Select all
mem_read: address 0x1000 out of range!
halt_sys: file sys.c, line 231
eax: 1234
Works
I'll try to map a BIOS into the memory and prepare a stack for executing my INT 10's.
- Combuster
- 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
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?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.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.Andy1988 wrote:Great. So, try and error on a hand full of machines and some praying or full io privileges... :-/
Never tried using a VGA driver as fallback?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).
-
- Member
- Posts: 170
- Joined: Wed Jul 18, 2007 5:51 am
Re: VBE from protected mode with vm86
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?
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?
- Owen
- Member
- Posts: 1700
- Joined: Fri Jun 13, 2008 3:21 pm
- Location: Cambridge, United Kingdom
- Contact:
Re: VBE from protected mode with vm86
Native drivers for what?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!
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)