- Store the current status of machine
- Load the old real mode data saved before this function
- Go back in real mode, perform the operation
- Enable again protected mode and jump back to my C++ code.
In order to do this, I saved the first 0x400 bytes of memory at start
Code: Select all
memcpy((void*)0x40000, (void*)0x0, 0x400);
Code: Select all
bios_mask[0]= inportb(0x21);
bios_mask[1] = inportb(0xa1);
Than, I disabled the interrupts with cli, I also remapped the pic and loaded the old bios values
Code: Select all
irq_remap(0x08,0x70);
outportb(0x21, bios_mask[0]);
outportb(0xA1, bios_mask[1]);
Code: Select all
memcpy((void*)0x40400, (void*)0x0, 0x400);
memcpy((void*)0x0, (void*)0x40000, 0x400);
Code: Select all
p_int86(&gp);
Code: Select all
org 0x0
; It is loaded in 0x40000
[bits 32]
TIMES 0x800 db 0
mov eax, cr0
mov [savcr0+0x40000], eax ; save pmode CR0
cli ; Disable interrupts.
lidt [idt_real+0x40000]
jmp dword 0x18:(start+0x40000)
idt_real:
dw 0x3ff ; 256 entries, 4b each = 1K
dd 0 ; Real Mode IVT @ 0x0000
savcr0:
dd 0 ; Storage location for pmode CR0.
start:
; We are already in 16-bit mode here!
[bits 16]
; Need 16-bit Protected Mode GDT entries!
mov eax, 0x20 ; 16-bit Protected Mode data selector.
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
; Disable paging (we need everything to be 1:1 mapped).
mov eax, cr0
and eax, 0x7FFFFFFe ; Disable paging bit & enable rmode.
mov cr0, eax
jmp 0x4000:GoRMode ; Perform Far jump to set CS.
GoRMode:
mov ax, 0x4000 ; Reset segment registers to 0x4000.
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
and eax,0xf0000
shr eax,4
mov ss, ax
mov eax, esp
and eax, 0xffff
mov sp, ax
sti
mov ebx,0
mov eax,0
mov ah,0x0
mov al,0
int 0x10
mov ah,0xe
mov al, '4'
mov bh,0
mov bl, 42
int 10h
hlt
On my old computer it works but I need to make a cli very early or it restarts. This happens only if I remap the pic, otherwise it works good.
In my new computer It doesn't restart, it doesn't work (the interrupts I mean because I tried simple code to emit a beep in real mode code and it works).
Have I missed anything? What could be wrong? Perhaps I forgot to set up something?
Oh yes this is my gdt
Code: Select all
gdt_set_gate(0, 0, 0, 0, 0);
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
gdt_set_gate(3, 0, 0xFFFFF, 0x9a, 0x00); //16bit code
gdt_set_gate(4, 0, 0xFFFFF, 0x92, 0x00); //16bit data