Executing a BIOS interrupt

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
seth
Posts: 1
Joined: Tue Jun 15, 2010 6:09 pm

Executing a BIOS interrupt

Post by seth »

Hello, I have a really newbie question.
I have a working kernel which is loaded by grub. I wanted to use BIOS interrupts to do some graphics related staff. How could i do this?
Basically what bothers me is that code needs to be under the 1MB mark (hope that I got this right). I don't like the x86emu as it is too big and my kernel would need a lot of change to implement virtual monitor.
Any ideas?
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Executing a BIOS interrupt

Post by NickJohnson »

You have to use either an emulator (like x86emu) or the virtual 8086 monitor. The monitor is easier and smaller. That or you can switch back to real mode, but that is probably more messy than the monitor, although it requires a less advanced kernel.
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: Executing a BIOS interrupt

Post by Combuster »

Congratulations, you just asked a Frequently Asked Question. :roll:
"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 ]
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Re: Executing a BIOS interrupt

Post by Ready4Dis »

NickJohnson wrote:You have to use either an emulator (like x86emu) or the virtual 8086 monitor. The monitor is easier and smaller. That or you can switch back to real mode, but that is probably more messy than the monitor, although it requires a less advanced kernel.
More messy? It's really not very hard or messy at all actually. This is my current method of using the VESA bios, however I have my emulator almost done now, which will help alleviate any latency, or interrupt issues I can currently have by dropping into real mode (and will also work when I switch over to 64-bit mode as well, which the v8086 monitor doesn't support without dropping back to 32-bit mode first, which is a hack at best). Anyways, the other thing is to use a more recent version of GRUB that will set the resolution for you and forget it. I prefer to be able to set the modes while my OS is running, and my VESA driver drops back to real-mode, calls int, and then back to p-mode. It happens very fast, but I don't like the solution, and have written a mostly functional (and pretty small) real mode emulator (I only need it to emulate real mode for bios calls, haven't run into a video bios that needed anything else yet) that can simulate a real-mode environment enough to call the video bios. The emulator runs in pmode as a seperate process, and is there for pre-emptable, and doesn't need any fancy hacks inside the kernel itself to support stuff. As long as it's a driver proc and has it's proper i/o permissions set, it doesn't interfere with anything else. Also, once I switch to long mode (64-bit), I can recompile my emulator as 64-bit program, and call 16-bit bios functions without any hacks (like dropping to pmode and using the v86, or dropping to pmode, then real mode, then back to pmode, back to long mode). Just seems like the best solution in the long run, and the best part is, it will be part of the driver not the kernel! so, when you write a real driver for your video card, the emulator isn't taking up space in your kernel like the rest of the other hacks would have to be special cases in your kernel code.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Executing a BIOS interrupt

Post by Owen »

Reasons why switching to real mode is a bad idea:
  • You have probably reconfigured all your peripherals in ways which the BIOS does not expect
  • The BIOS is liable to enable interrupts, then get hit by something it wasn't expecting
  • VBE mode switches take time. Anything which needs accurate timing is going to lose it. If you have any data being recieved on a serial port, its gonna get lost.
  • If you decide to vector interrupts back to protected/long mode to alleviate that issue, things get hellishly complex
Theres more which Brendan can probably elaborate on which I haven't covered here. Your best option is, like Ready4Dis stated, using an emulator; I presume his is in a good state, another alternative is x86emu (Which is embedded somewhere inside the X.org sources)
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Executing a BIOS interrupt

Post by bewing »

I've also created an emulator based on my ReBochs. It's very complete, and only compiles to 124K. (It also needs people to test it lots! :) )
User avatar
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: Executing a BIOS interrupt

Post by Creature »

Owen wrote:Reasons why switching to real mode is a bad idea:
  • You have probably reconfigured all your peripherals in ways which the BIOS does not expect
  • The BIOS is liable to enable interrupts, then get hit by something it wasn't expecting
  • VBE mode switches take time. Anything which needs accurate timing is going to lose it. If you have any data being recieved on a serial port, its gonna get lost.
  • If you decide to vector interrupts back to protected/long mode to alleviate that issue, things get hellishly complex
Theres more which Brendan can probably elaborate on which I haven't covered here. Your best option is, like Ready4Dis stated, using an emulator; I presume his is in a good state, another alternative is x86emu (Which is embedded somewhere inside the X.org sources)
From what I've seen up until now I think it's just easiest to get an emulator as soon as possible straight away. Just because it works in long mode and works with a lot of interrupts out-of-the-box. Writing one yourself can be time-consuming however. Someone posted one not so long ago in the Announcements section (I believe it was thepowersgang) licensed under the BSD license. I'm going to stick to dropping to real mode for now (I don't really need BIOS interrupts yet anyway, it's just for testing VBE occasionally) and IMHO VM86 is way too complex to write and error-prone (I seem to have a heap that keeps bugging out every once in a while, causing all depending components like multithreading/multitasking to mess up as well) for me to work only in protected mode and is not going to be useful in long mode anyway (should I ever start on it).
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
Selenic
Member
Member
Posts: 123
Joined: Sat Jan 23, 2010 2:56 pm

Re: Executing a BIOS interrupt

Post by Selenic »

With respect to the idea of using a non-v86 emulator, I seem to remember a comment about it taking considerably longer than doing it via rmode. I think this problem could be solved by, instead of writing an interpreter, write a translator - in other words, create a copy of the BIOS code in memory, but with register prefixes and so on modified so it works in 32-bit (or 64-bit) mode. If this worked it should be basically as fast as the original, minus a one-off translation cost (which shouldn't even be that high)

Of course, it's probably not as easy as writing an interpreter - a few examples I can think of: 'inc/dec reg' (in rmode/pmode, these have one-byte opcodes. In lmode, those opcodes are REX prefixes), dealing with segmentation and addressing (IIRC, as an example, one of the 'register' values in rmode is [bp+bx], which needs a SIB byte in non-rmode)

Edit: thinking about it a bit more, is the extra effort needed for my idea even worth it? You're often not going to care if it takes a couple of seconds longer to change video mode, plus an emulator can be used to interpret the video BIOS (and therefore use VBE) even on non-x86 systems.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Executing a BIOS interrupt

Post by Brendan »

Hi,
Selenic wrote:With respect to the idea of using a non-v86 emulator, I seem to remember a comment about it taking considerably longer than doing it via rmode. I think this problem could be solved by, instead of writing an interpreter, write a translator - in other words, create a copy of the BIOS code in memory, but with register prefixes and so on modified so it works in 32-bit (or 64-bit) mode. If this worked it should be basically as fast as the original, minus a one-off translation cost (which shouldn't even be that high)
Translating real mode code into protected mode code isn't easy (certainly a lot harder than simply inserting size override prefixes). Consider something like "jmp far [bx]" where BX is calculated from several things. Basically you end up writing the equivalent of a JIT compiler (where all paths are taken), which is just another form of emulator.

Switching back to real mode (when the OS is running and all the hardware has been reconfigured) is probably the most complex method. However, switching back to real mode (during boot before you've touched any of the hardware) is by far the simplest method.

The other thing you're overlooking is U/EFI. Microsoft got around to supporting it (on 64-bit 80x86) a while ago; which allows motherboard manufacturers to support it without worrying about sales, and they are finally (but slowly) switching to U/EFI (e.g. from not long ago); and we all know (80x86) Apple has been using it for a while. Newer versions of GRUB2 also support it. Basically you shouldn't assume that the BIOS or any BIOS/VBE functions exist.

IMHO the "most sane" option is to setup a video mode during boot (e.g. in the boot loader, using VBE for boot loaders designed for "PC BIOS", using U/EFI for boot loaders designed for U/EFI, and using "whatever" for boot loaders designed for "whatever") and use native video drivers after boot. The disadvantage here is that it means the user needs to reboot to change video modes if no native video driver is present; but people don't change video modes often (especially if the code using video is "resolution independent" like it should be for a modern OS) unless they're playing 3D games (where the user is screwed without a native video driver that supports 3D acceleration anyway).

However, this still creates some problems for people who rely on GRUB. GRUB-legacy doesn't support video mode switching unless it's been patched (but you can't really assume it has been patched, especially when people are adding your OS to an existing system with an existing version of GRUB). The best way to get around that is to switch back to real mode and setup a video mode yourself using VBE (which is how I've always used GRUB anyway). For GRUB2 you're screwed - there's no way to determine if the firmware is "PC BIOS" (or U/EFI, or coreboot, or OpenFirmware, or whatever) so you have to rely on GRUB to setup a video mode; which mostly means that you have to rely on the end-user to setup GRUB and make sure you end up with a video mode that is supported by the video card, the monitor and your OS (and this also means that you can't create a generic bootable CD that works in all computers unless you stick to standard VGA video modes like 640*480*16-colours, because not all computers support the same video modes).

To be honest, I'm not sure how I'm going to deal with GRUB2 myself - I usually put a lot of effort into auto-detection and "configuration-less" boot, and aren't happy with the idea of forcing the end user sort it out (rather than having an automatically selected video mode that is guaranteed to work without hassling the user, and allowing the user choose if they don't like the automatically selected video mode). Of course I write my own boot loaders (and also support GRUB for convenience) so it's likely that I'll be supporting GRUB on PC BIOS systems (and switching back to real mode to setup video myself) and telling everyone using other types of firmware that they have to use a native boot loader (and not GRUB2).


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
Creature
Member
Member
Posts: 548
Joined: Sat Dec 27, 2008 2:34 pm
Location: Belgium

Re: Executing a BIOS interrupt

Post by Creature »

Brendan wrote:...
I agree with the GRUB2 EFI thing. One thing I've always disliked about OSDev is that sometimes, there are just too many "what if"-cases where you have to take an enormous amount of possibilities into account. What if the user doesn't have this resolution? What if the monitor doesn't support it? What if there's EFI? Is there VBE available? And in theory, you should be able to handle it all. The good part is that it is possible (although it can be time-consuming), but the crappy thing about it is that you have hardware and hardware: none of them are alike and they all have their quirks and differences you have to take into account. At this time, I'm just writing a hobby OS, not much caring about all these quirks (I'm writing it mostly for fun anyway, and I'm tired of worrying about all these things).
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Executing a BIOS interrupt

Post by Brendan »

Hi,
Creature wrote:I agree with the GRUB2 EFI thing. One thing I've always disliked about OSDev is that sometimes, there are just too many "what if"-cases where you have to take an enormous amount of possibilities into account.
I used to be like that, but in a way I like the challenge (e.g. the feeling you get when you've finally "beaten" it).

Of course it's also possible to limit the range of hardware/firmware your OS supports. A good example of this is the "we only care about the hardware we sell and refuse to support generic 80x86" approach that Apple uses.


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.
Benjamin1996
Member
Member
Posts: 78
Joined: Sat Apr 10, 2010 7:00 am
Location: Denmark

Re: Executing a BIOS interrupt

Post by Benjamin1996 »

The way I got it, you can go waaay over 1MB if you enable the A20 line, and configure your GDT right.
Post Reply