Page 1 of 3

I can't switch back to real mode properly (Gave up)

Posted: Sat May 21, 2016 10:42 am
by Ycep
Hi, i was trying to call interrupts to get in graphics mode. I done that before by doing this in bootloader:

Code: Select all

mov ah, 0
mov al, 0x12
int 0x10
Now i want to do it in kernel.
Remember my last post : http://forum.osdev.org/viewtopic.php?f=1&t=30380? OK, there i tried to call interrupts.
To get into real mode i do this:

Code: Select all

cli
mov eax, cr0
and eax, 0
mov cr0, eax
sti
In __asm block. I just change first bit in CR0.
To get back to protected mode, i do this:

Code: Select all

cli
mov eax, cr0
xor eax, 1
mov cr0, eax
		
mov ax, 0
mov ds, ax
mov fs, ax
mov es, ax
mov gs, ax
mov ss, ax
mov esp, 2097000
I remove that first bit from CR0, reset segment registers and set stack 2097000 (It's always at that location. My OS requires minimum 2MB of RAM.)

It seem to halt at int 0x10. That means somehow, it's still in protected mode.
Hmmm, i do not get to real mode right.
Any ideas to fix this?
Yeah, also removed deadline from my website.

Re: I can't switch back to real mode properly

Posted: Sat May 21, 2016 11:18 am
by BrightLight
If your kernel is loaded above 1 MB, you have a problem. You'll need to set up a stub in low memory (below 640 KB).
Disable interrupts and restore the PIC to original BIOS state (master PIC using vector 0x08, and slave 0x70). Next, make sure you are at an identity-paged memory address, and disable paging as so:

Code: Select all

mov eax, cr0
and eax, 0x7FFFFFFF    ; clear PG bit
mov cr0, eax
Then jump to a 16-bit protected mode code segment, and set all data segments to 16-bit protected mode data segments. Then, disable protection:

Code: Select all

mov eax, cr0
and eax, 0xFFFFFFFE    ; clear PE bit
mov cr0, eax
Then jump to real mode code with a normal real mode code segment (not in the GDT) and set all data segments. Load the BIOS Interrupt Vector Table (base 0x00000000 limit 0x03FF) and enable interrupts.
P.S: Just a tip, don't make deadlines. For any project, not just yours, it's easily to be late for a deadline which will just disappoint you and your audience.

Re: I can't switch back to real mode properly

Posted: Sat May 21, 2016 12:00 pm
by Ycep
omarrx024 wrote: restore the PIC to original BIOS state
Load the BIOS Interrupt Vector Table (base 0x00000000 limit 0x03FF).
Questions:
  • 1. Do i need to do these quoted things?
    2. If so what is "PIC original BIOS state" and how could i load IVT?
    3. What is "16-bit protected mode data segment"?
I'm just an beginner, and i don't like IVT, GDT and other craps.

Re: I can't switch back to real mode properly

Posted: Sat May 21, 2016 4:06 pm
by neon
Hello,

1. Yes, they are both needed for real mode.
2. The PIC should be programmed such that IRQ's 0-33 map to IVT entries 0-33 respectively. For protected mode, you had to remap the PIC because the default PIT timer maps to the double fault exception handler.
3. Its just a GDT selector with the 16 bit flag set. You should have both a 16 bit code selector and 16 bit data selector. You need to jump to 16 bit protected mode before being able to drop to 16 bit real mode.
I'm just an beginner, and i don't like IVT, GDT and other craps.
Why are you wanting to build something without actually learning anything about what you intend to build?

In any case, you should be using virtual 8086 mode rather then real mode for calling BIOS services when you are at the kernel stage. Dropping down to real mode is fine in a boot loader environment, however it becomes increasingly impossible to do properly in later stages -- so use virtual 8086 mode.

Re: I can't switch back to real mode properly

Posted: Sat May 21, 2016 6:07 pm
by BrightLight
Virtual 8086 mode adds to the complexity, and has its limitations as well. Besides, I assume using real mode just for video mode changes is fine; how often do you change your screen resolution?
neon wrote:The PIC should be programmed such that IRQ's 0-33 map to IVT entries 0-33 respectively. For protected mode, you had to remap the PIC because the default PIT timer maps to the double fault exception handler.
The PIC should be programmed so that IRQs 0-7 use IVT entries 0x08-0x0F, and IRQs 8-15 use IVT entries 0x70-0x77. It is not possible to have 33 IRQs with the PIC, and IRQ 0 is not INT 0. ;)

Re: I can't switch back to real mode properly

Posted: Sat May 21, 2016 6:49 pm
by Brendan
Hi,
omarrx024 wrote:Virtual 8086 mode adds to the complexity, and has its limitations as well.
Yes. However not using virtual8086 also adds complexity (e.g. trying to figure out how to prevent things from locking up because various IRQs occurred when you happened to be in real mode and the device drivers responsible for those devices don't get the IRQs).
omarrx024 wrote:Besides, I assume using real mode just for video mode changes is fine; how often do you change your screen resolution?
For some statistics (not enough to consider a survey)...

For this computer I haven't changed a video mode since I replaced the second monitor about 5 years ago. For the other/newer computer I use (mostly for games) I don't think I've ever changed the video mode (but have changed the video card). Mostly; I change the screen resolution less often than I change the hardware.

The main reason for this is that modern monitors have a native resolution, and that's the only resolution you ever really want (as long as the software you use isn't extremely broken and does allows you to adjust things like font sizes, etc). ;)


Cheers,

Brendan

Re: I can't switch back to real mode properly

Posted: Sat May 21, 2016 7:18 pm
by neon
Hello,
omarrx024 wrote:The PIC should be programmed so that IRQs 0-7 use IVT entries 0x08-0x0F, and IRQs 8-15 use IVT entries 0x70-0x77. It is not possible to have 33 IRQs with the PIC, and IRQ 0 is not INT 0. ;)
Whoops, you are right here, my mistake. I wouldn't say that it "should" be programmed that way however - it could be remapped any number of ways, so long as it does not result in conflicts with reserved vectors. (If interested, I was thinking of reserved vectors rather then PIC IRQ lines, idk why.)

I would have to disagree with you regarding real mode however for many of the reasons Brendan provided above. The firmware expects the system to be in a predetermined state, however you need to modify that state which creates incompatibilities and problems between what the firmware expects and what your system software expects. Besides, virtual 8086 mode really isn't all that complicated for what we need. For video, all you need to support is the emulation of the int instruction and perhaps the i/o permissions bitmap.

I don't typically object to the use of real mode in boot loaders or boot managers because they don't typically create conflicts due to their dependency on boot firmware services. However, once the operating system takes control and begins to change things around, things become much more complicated rather quickly to the point where real mode is practically impossible to achieve.

Re: I can't switch back to real mode properly

Posted: Sat May 21, 2016 8:14 pm
by BrightLight
neon wrote:I would have to disagree with you regarding real mode however for many of the reasons Brendan provided above. The firmware expects the system to be in a predetermined state, however you need to modify that state which creates incompatibilities and problems between what the firmware expects and what your system software expects. Besides, virtual 8086 mode really isn't all that complicated for what we need. For video, all you need to support is the emulation of the int instruction and perhaps the i/o permissions bitmap.
Well, I'm quite sure many graphics cards don't use I/O ports and everything is memory-mapped, which means the BIOS will have to go into protected mode to access hardware MMIO registers in high memory, and v8086 isn't capable of doing that. I'd say even after the kernel has configured everything, going into real mode once a year to change the screen resolution is fine.
Another solution of course, is CPU emulation, but that complicates things even more...

Re: I can't switch back to real mode properly

Posted: Sat May 21, 2016 9:07 pm
by Brendan
Hi,
omarrx024 wrote:
neon wrote:I would have to disagree with you regarding real mode however for many of the reasons Brendan provided above. The firmware expects the system to be in a predetermined state, however you need to modify that state which creates incompatibilities and problems between what the firmware expects and what your system software expects. Besides, virtual 8086 mode really isn't all that complicated for what we need. For video, all you need to support is the emulation of the int instruction and perhaps the i/o permissions bitmap.
Well, I'm quite sure many graphics cards don't use I/O ports and everything is memory-mapped, which means the BIOS will have to go into protected mode to access hardware MMIO registers in high memory, and v8086 isn't capable of doing that.
Typically a video card either uses IO ports or uses the "legacy VGA" area (at 0x0000A0000) for memory mapped registers; and v8086 works for either of those cases.

The main problems with v8086 is that it won't work for long mode/64-bit and doesn't help for UEFI, and both of these things mean that it's a dead end (can't be used on most modern and future computers).
omarrx024 wrote:I'd say even after the kernel has configured everything, going into real mode once a year to change the screen resolution is fine.
Another solution of course, is CPU emulation, but that complicates things even more...
I'd say that it's better to just setup a video mode during boot (while you can still use UEFI services and/or VBE, before the OS takes control of the hardware) and then not bother supporting video mode switches after boot unless there's a native video driver. You could even get boot loader to provide a list of video modes and have a "set boot parameter that tells boot loader which video mode you want, then reboot" thing so that the user is still able to select a video mode while the OS is running (e.g. using a pretty dialog box/tool). Anything more complicated than that (e.g. v8086, an emulator, etc) is too much work for something nobody cares about 99.99% of the time, and there's always something else that you could spend the time on that is more important.


Cheers,

Brendan

Re: I can't switch back to real mode properly

Posted: Sat May 21, 2016 9:18 pm
by neon
The main problems with v8086 is that it won't work for long mode/64-bit and doesn't help for UEFI, and both of these things mean that it's a dead end (can't be used on most modern and future computers).
It is my (although limited) understanding that the VT-x technology adds back the capability to run virtual 8086 mode from long mode. But I suppose it doesn't matter anyways since UEFI is slowly replacing legacy BIOS.

Re: I can't switch back to real mode properly

Posted: Sun May 22, 2016 3:01 am
by Ycep
neon wrote:Hello,

1. Yes, they are both needed for real mode.
2. The PIC should be programmed such that IRQ's 0-33 map to IVT entries 0-33 respectively. For protected mode, you had to remap the PIC because the default PIT timer maps to the double fault exception handler.
3. Its just a GDT selector with the 16 bit flag set. You should have both a 16 bit code selector and 16 bit data selector.
Why are you wanting to build something without actually learning anything about what you intend to build?
How should descriptor with 16 bit flag look like?

Re: I can't switch back to real mode properly

Posted: Sun May 22, 2016 5:03 am
by Techel
In a descriptor within the gdt there's a size-flag. Have a look: http://wiki.osdev.org/Global_Descriptor_Table

Re: I can't switch back to real mode properly

Posted: Sun May 22, 2016 9:17 am
by Ycep
Techel wrote:In a descriptor within the gdt there's a size-flag. Have a look: http://wiki.osdev.org/Global_Descriptor_Table
I asked something like how it does look. I mean, which is granularity, access, base, limit, etc.
Example:
Granularity bit is set to 1
Access is Read only
Base is 0
Limit is 0xDEADBEEF
OK?

Re: I can't switch back to real mode properly

Posted: Sun May 22, 2016 4:35 pm
by pcmattman
No, the wiki page is sufficient and in fact appears to essentially answer your request. Spoon-feeding won't get you anywhere in OSDev.

Re: I can't switch back to real mode properly

Posted: Sun May 22, 2016 10:12 pm
by neon
Hello,

Honestly, the only thing you need to change is that one bit. You can literally copy and paste the code that creates the 32 bit code/data descriptors and change that one size bit for each to create two new 16 bit code/data descriptors. Do you know what all of the fields in the GDT entries actually are? Have you read what was provided to you? Was there any questions or doubts that you had regarding what you read?

I can easily provide source for you - but to be honest, unless you actually know what it does, why it does it, (i.e. you can already write it yourself) I can assure you that you will have trouble using it properly. You really do need to read and understand the provided material before attempting this - there is no short cuts this time. If you copy and paste code that does this, you'll run into problem after problem.

By the way, you can't go into 16 bit protected mode (nor real mode) using inline assembly. You'll have to use an external assembler, such as nasm.