Calling realmode ints after multiboot (without v86)

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
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Calling realmode ints after multiboot (without v86)

Post by jal »

Since I'm having trouble getting GRUB to pass me VBE information so I can use the PM interface to switch modes (see this topic), I thought I'd try to call the realmod (BIOS) interrupts. However, how do I do that? My kernel is not yet in a stage that I can think about v86. So how do I switch back to realmode, after my kernel has been booted by GRUB (or any other multiboot compliant bootloader for that matter)? GRUB already sets me up in PM, so how to switch back? Yeah, I know about bit 0 of CR0 and such, but how do I get the correct realmode segments? Any help would be much appreciated.


JAL
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Calling realmode ints after multiboot (without v86)

Post by Brendan »

Hi,
jal wrote:Since I'm having trouble getting GRUB to pass me VBE information so I can use the PM interface to switch modes (see this topic), I thought I'd try to call the realmod (BIOS) interrupts. However, how do I do that? My kernel is not yet in a stage that I can think about v86. So how do I switch back to realmode, after my kernel has been booted by GRUB (or any other multiboot compliant bootloader for that matter)? GRUB already sets me up in PM, so how to switch back? Yeah, I know about bit 0 of CR0 and such, but how do I get the correct realmode segments? Any help would be much appreciated.
I've done this before (for the same reason you're doing it).

The basic idea is to copy some code from where GRUB loaded it to below 1 MB. Then jump/call this code below 1 MB, setup a new GDT, change all segment registers (including CS and SS) so they point to 16-bit protected mode segments, then clear the PE bit in CR0. Now you're in real mode or "unreal" mode (it's just as easy to leave 4 GB segment limits on data segment registers). Do a far JMP to reload CS and flush the pipeline, then do STI to enable interrupts.

Now you should be able to use the BIOS functions like normal. :)

Note: for segment registers, the only thing that really matters is that CS and SS are 16-bit protected mode segments before you clear the PE flag in CR0 (and that all segment limits are 64 KB or larger).

There is one (small) problem though. The Multi-boot specification says that the boot loader (e.g. GRUB) must keep the firmware in a working state, however, it doesn't say the firmware must be PC BIOS. If GRUB was booted by different firmware (e.g. LinuxBIOS or EFI) then you'll crash when you try to use PC BIOS functions.


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.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Calling realmode ints after multiboot (without v86)

Post by jal »

Brendan wrote:There is one (small) problem though. The Multi-boot specification says that the boot loader (e.g. GRUB) must keep the firmware in a working state, however, it doesn't say the firmware must be PC BIOS. If GRUB was booted by different firmware (e.g. LinuxBIOS or EFI) then you'll crash when you try to use PC BIOS functions.
Well, I don't believe GRUB classic supports EFI or LinuxBIOS, and I'm running in Bochs for the moment, so no problem there. Thanks for the information, I'll try to hack something together to see if that works.


JAL
Post Reply