I am trying to switch to a graphics mode so I can do some drawing in my OS. I've had some success with changing my multiboot header for grub, but from what I've seen here it's a bit of a nasty approach.. So I've decided to attempt the most recommended solution, switching to real mode to call the interrupt and switch video modes, then switching back.
I've seen a bunch of ways to do this, but is there a standard way to switch to real mode and back?
Also, if this isn't in fact the best solution, what would you guys suggest?
Thanks.
If needed, here's my basic stuff I've got working:
- paging
- gdt/idt/keyboard driver/interrupt handling
- basic shell and timer
PMode to Real and back
Re: PMode to Real and back
Hello,
The recommended approach (and, really, the only reliable options) would be to support virtual 8086 mode or using custom device drivers. The method you described (falling back to real mode) is only reliable in protected mode boot loaders provided the hardware has not been reconfigured to be incompatible with what the firmware expects. It is also reliant on BIOS firmware that implement VGA or VBE services - which is less and less common as the industry slowly adopts to EFI firmware.
Thus the best solutions past the boot loader stage are virtual 8086 mode and writing custom device drivers. Virtual 8086 mode is recommended; however we do encourage writing custom drivers for Bochs, QEmu, and Virtual Box. For Intel chip sets, you might also be able to write drivers provided you have the appropriate documentation available. It should be noted however that you would be entirely on your own. Virtual 8086 mode is easier and recommended to support anyways - however is slower and you need to be careful with implementing it properly.
Please note that you were asking for the "best" solution. However the best solutions are almost never the simplest.
The recommended approach (and, really, the only reliable options) would be to support virtual 8086 mode or using custom device drivers. The method you described (falling back to real mode) is only reliable in protected mode boot loaders provided the hardware has not been reconfigured to be incompatible with what the firmware expects. It is also reliant on BIOS firmware that implement VGA or VBE services - which is less and less common as the industry slowly adopts to EFI firmware.
Thus the best solutions past the boot loader stage are virtual 8086 mode and writing custom device drivers. Virtual 8086 mode is recommended; however we do encourage writing custom drivers for Bochs, QEmu, and Virtual Box. For Intel chip sets, you might also be able to write drivers provided you have the appropriate documentation available. It should be noted however that you would be entirely on your own. Virtual 8086 mode is easier and recommended to support anyways - however is slower and you need to be careful with implementing it properly.
Please note that you were asking for the "best" solution. However the best solutions are almost never the simplest.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Re: PMode to Real and back
Hi,
In my opinion; the best solution is for the boot loader to use the firmware (VGA/VBE BIOS functions or UEFI's GOP/UGA) to setup a default video mode that the monitor, video card and OS all support. Later during boot (after kernel is initialised and you're starting device drivers), if the OS actually has native video drivers to suit the video card then they can take over.
However, when you're using multi-boot this isn't reliable. Some mutli-boot boot loaders don't support any of the video stuff at all, if the kernel's "preferred video mode" isn't supported the boot loader could choose anything including video modes that the OS doesn't support, and it's "unintelligent" (e.g. you can't have a generic boot CD that intelligently decides the best video mode based on monitor size, CPU speed, etc).
For these reasons; when using multi-boot; I'd recommend having your own "stage 2" instead of a kernel, where your "stage 2" switches to real mode and sets up a video mode properly (and possibly does other things), then sets up the real kernel (possibly including initialising paging and switching to long mode, etc) and starts the kernel (where the kernel would have been loaded as a module by GRUB).
Note that multi-boot guarantees that the firmware is left in a usable state; but there's no way to know if the firmware is BIOS or UEFI, and if the firmware is UEFI it won't be left in a usable state (e.g. GRUB has to ignore the multi-boot spec in this case and will call UEFI's "exit boot services" because the OS can't) and attempting to use BIOS functions will cause the OS to crash instead. This can be solved by having a decent UEFI boot loader for UEFI systems that replaces both GRUB and your "stage 2".
Switching to real mode is relatively simple - you'd copy some code into the first 1 MIB of the physical address space, load a GDT with "64 KiB 16-bit descriptors", load those descriptors (so you get 16-bit protected mode), then disable protected mode in CR0, and load real mode segments.
Implementing support for virtual8086 mode is much more complicated. It's not necessary for a boot loader (which can safely use real mode) to use virtual8086 mode. It would be necessary to use virtual8086 mode (or a real mode emulator implemented in software if you're in long mode) after boot (e.g. after the OS has taken control of the hardware and the firmware's assumptions are no longer valid); but "driver-less video mode switches" are the only slightly sane reason to use the BIOS after boot; and being able to do "driver-less video mode switches" after boot isn't necessary (e.g. it's an irrelevant luxury) and it'd be better to spend your time writing native video drivers (e.g. that are capable of setting the full range of video modes and can support systems with multiple monitors, etc) instead of wasting time implementing support for "driver-less video mode switches".
Cheers,
Brendan
In my opinion; the best solution is for the boot loader to use the firmware (VGA/VBE BIOS functions or UEFI's GOP/UGA) to setup a default video mode that the monitor, video card and OS all support. Later during boot (after kernel is initialised and you're starting device drivers), if the OS actually has native video drivers to suit the video card then they can take over.
However, when you're using multi-boot this isn't reliable. Some mutli-boot boot loaders don't support any of the video stuff at all, if the kernel's "preferred video mode" isn't supported the boot loader could choose anything including video modes that the OS doesn't support, and it's "unintelligent" (e.g. you can't have a generic boot CD that intelligently decides the best video mode based on monitor size, CPU speed, etc).
For these reasons; when using multi-boot; I'd recommend having your own "stage 2" instead of a kernel, where your "stage 2" switches to real mode and sets up a video mode properly (and possibly does other things), then sets up the real kernel (possibly including initialising paging and switching to long mode, etc) and starts the kernel (where the kernel would have been loaded as a module by GRUB).
Note that multi-boot guarantees that the firmware is left in a usable state; but there's no way to know if the firmware is BIOS or UEFI, and if the firmware is UEFI it won't be left in a usable state (e.g. GRUB has to ignore the multi-boot spec in this case and will call UEFI's "exit boot services" because the OS can't) and attempting to use BIOS functions will cause the OS to crash instead. This can be solved by having a decent UEFI boot loader for UEFI systems that replaces both GRUB and your "stage 2".
Switching to real mode is relatively simple - you'd copy some code into the first 1 MIB of the physical address space, load a GDT with "64 KiB 16-bit descriptors", load those descriptors (so you get 16-bit protected mode), then disable protected mode in CR0, and load real mode segments.
Implementing support for virtual8086 mode is much more complicated. It's not necessary for a boot loader (which can safely use real mode) to use virtual8086 mode. It would be necessary to use virtual8086 mode (or a real mode emulator implemented in software if you're in long mode) after boot (e.g. after the OS has taken control of the hardware and the firmware's assumptions are no longer valid); but "driver-less video mode switches" are the only slightly sane reason to use the BIOS after boot; and being able to do "driver-less video mode switches" after boot isn't necessary (e.g. it's an irrelevant luxury) and it'd be better to spend your time writing native video drivers (e.g. that are capable of setting the full range of video modes and can support systems with multiple monitors, etc) instead of wasting time implementing support for "driver-less video mode switches".
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: PMode to Real and back
The topic of video modes is an on-going issue that seems to be present all the time, at least once in a few months. It makes things a lot easier if we just left the BIOS routines behind us after passing the boot loader stages. Having an LFB set up by a boot loader (either BIOS or UEFI), avoiding really inconvenient pixel modes, creating a standard video mode information structure and passing it forward makes things very easy. After the boot stages, it is not necessary to care whether the BIOS or UEFI set up the mode.