From cdd784fd1973c345332ee124127e371ff56f4e42 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Tue, 14 Jun 2011 12:17:28 +0000 Subject: [PATCH] [FREELDR] Start implementing a realmode callback mechanism svn path=/trunk/; revision=52226 --- .../boot/freeldr/freeldr/arch/i386/entry.S | 55 +++++++++++++- .../boot/freeldr/freeldr/arch/realmode/i386.S | 76 +++++++++++++++++-- .../freeldr/freeldr/arch/realmode/int386.inc | 57 ++++++++++++++ .../freeldr/include/arch/pc/x86common.h | 21 ++++- 4 files changed, 198 insertions(+), 11 deletions(-) create mode 100644 reactos/boot/freeldr/freeldr/arch/realmode/int386.inc diff --git a/reactos/boot/freeldr/freeldr/arch/i386/entry.S b/reactos/boot/freeldr/freeldr/arch/i386/entry.S index 4abacd938fb..629bdabfffe 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/entry.S +++ b/reactos/boot/freeldr/freeldr/arch/i386/entry.S @@ -44,9 +44,9 @@ _RealEntryPoint: lidt i386idtptr /* Continue execution */ - jmp dword ptr [_ContinueAddress] + jmp dword ptr [ContinueAddress] -_ContinueAddress: +ContinueAddress: .long _FrldrStartup @@ -59,6 +59,12 @@ _FrldrStartup: mov al, dh mov dword ptr [_FrldrBootPartition], eax + /* Patch long jump with real mode entry point */ + mov eax, dword ptr ds:[BSS_RealModeEntry] + mov dword ptr ds:[SwitchToReal16Address], eax + +call _Int386_ // test + /* GO! */ xor eax, eax push eax @@ -216,6 +222,51 @@ PUBLIC _EnableA20 _EnableA20: ret +PUBLIC _Int386_ +_Int386_: + /* Save all registers + segment registers */ + push ds + push es + push fs + push gs + pusha + + /* Set the callback index */ + mov cx, 1234 + + /* Set continue address and switch to real mode */ + mov dword ptr [ContinueAddress], offset Int386_return + jmp SwitchToReal + +Int386_return: + + popa + pop gs + pop fs + pop es + pop ds + ret + + +SwitchToReal: + /* Set sane segments */ + mov ax, PMODE_DS + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + /* Save 32-bit stack pointer */ + mov dword ptr [stack32], esp + + /* jmp to 16-bit segment to set the limit correctly */ + .byte HEX(0ea) // jmp far RMODE_CS:switch_to_real16 +SwitchToReal16Address: + .long 0 // receives address of switch_to_real16 + .word RMODE_CS + nop + /* Multiboot support * diff --git a/reactos/boot/freeldr/freeldr/arch/realmode/i386.S b/reactos/boot/freeldr/freeldr/arch/realmode/i386.S index a6f88e8e038..2bfdaef5b17 100644 --- a/reactos/boot/freeldr/freeldr/arch/realmode/i386.S +++ b/reactos/boot/freeldr/freeldr/arch/realmode/i386.S @@ -30,6 +30,9 @@ RealModeEntryPoint: /* Enable A20 address line */ call EnableA20 + /* Safe real mode entry point in shared memory */ + mov dword ptr [BSS_RealModeEntry], offset switch_to_real16 + /* Get address of optional header */ mov eax, dword ptr ds:[FREELDR_PE_BASE + IMAGE_DOS_HEADER_e_lfanew] add eax, FREELDR_PE_BASE + 4 + IMAGE_FILE_HEADER_SIZE @@ -38,20 +41,74 @@ RealModeEntryPoint: mov eax, dword ptr ds:[eax + IMAGE_OPTIONAL_HEADER_AddressOfEntryPoint] add eax, FREELDR_PE_BASE - /* Safe the entry point */ - mov dword ptr [BSS_EntryPoint], eax - /* Patch the long jump instruction */ mov word ptr [pm_offset], ax + jmp exit_to_protected + + +/* This is the entry point from protected mode */ +switch_to_real16: + + /* Restore segment registers to correct limit */ + mov ax, RMODE_DS + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + /* Disable Protected Mode */ + mov eax, cr0 + and eax, CR0_PE_CLR + mov cr0, eax + + /* Clear prefetch queue & correct CS */ + ljmp16 0, inrmode + +inrmode: + /* Set real mode segments */ + xor ax, ax + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + /* Clear out the high 16-bits of ESP */ + /* This is needed because I have one */ + /* machine that hangs when booted to dos if */ + /* anything other than 0x0000 is in the high */ + /* 16-bits of ESP. Even though real-mode */ + /* code should only use SP and not ESP. */ + xor esp, esp + + /* Restore real mode stack */ + mov sp, word ptr ds:[stack16] + + /* Load IDTR with real mode value */ + lidt rmode_idtptr + + sti /* These are ok now */ + + /* Do the callback, specified by cx */ + // call word ptr CallbackTable[cx * 4] + mov ax, cx + call writehex4 + /* * Switches the processor to protected mode * it destroys eax */ -switch_to_prot: +exit_to_protected: + + cli + + /* Safe current stack pointer */ + mov word ptr ds:[stack16], sp /* Load the GDT */ - lgdt gdtptr + lgdt gdtptr /* Enable Protected Mode */ mov eax, cr0 @@ -67,6 +124,7 @@ pm_offset: + /* 16-bit stack pointer */ stack16: .word STACK16ADDR @@ -109,8 +167,14 @@ gdtptr: .word HEX(27) /* Limit */ .long gdt /* Base Address */ -.org 1024 +/* Real-mode IDT pointer */ +rmode_idtptr: + .word HEX(3ff) /* Limit */ + .long 0 /* Base Address */ +//.org 1024 + +#include "int386.inc" #include "helpers.inc" .org (FREELDR_PE_BASE - FREELDR_BASE) diff --git a/reactos/boot/freeldr/freeldr/arch/realmode/int386.inc b/reactos/boot/freeldr/freeldr/arch/realmode/int386.inc new file mode 100644 index 00000000000..c96c900a6b9 --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/realmode/int386.inc @@ -0,0 +1,57 @@ + + +Int386: + /* Get the interupt vector and patch the opcode */ + mov al, byte ptr ds:[BSS_IntVector] + mov byte ptr ds:[Int386_vector_opcode], al + + /* Setup the registers */ + mov ax, word ptr cs:[BSS_RegisterSet + REGS_DS] + mov ds, ax /* DS register */ + mov ax, word ptr cs:[BSS_RegisterSet + REGS_ES] + mov es, ax /* ES register */ + mov ax, word ptr cs:[BSS_RegisterSet + REGS_FS] + mov fs, ax /* FS register */ + mov ax, word ptr cs:[BSS_RegisterSet + REGS_GS] + mov gs, ax /* GS register */ + + mov eax, dword ptr cs:[BSS_RegisterSet + REGS_EAX] /* EAX register */ + mov ebx, dword ptr cs:[BSS_RegisterSet + REGS_EBX] /* EBX register */ + mov ecx, dword ptr cs:[BSS_RegisterSet + REGS_ECX] /* ECX register */ + mov edx, dword ptr cs:[BSS_RegisterSet + REGS_EDX] /* EDX register */ + mov esi, dword ptr cs:[BSS_RegisterSet + REGS_ESI] /* ESI register */ + mov edi, dword ptr cs:[BSS_RegisterSet + REGS_EDI] /* EDI register */ + + /* Do not set the flags register */ + /* only return its value in regsout */ + + /* Call the interrupt vector */ + /*int Int386_vector*/ + .byte 0xcd +Int386_vector_opcode: + .byte 0x00 + + /* Save the registers */ + mov dword ptr cs:[BSS_RegisterSet + REGS_EAX], eax /* EAX register */ + mov dword ptr cs:[BSS_RegisterSet + REGS_EBX], ebx /* EBX register */ + mov dword ptr cs:[BSS_RegisterSet + REGS_ECX], ecx /* ECX register */ + mov dword ptr cs:[BSS_RegisterSet + REGS_EDX], edx /* EDX register */ + mov dword ptr cs:[BSS_RegisterSet + REGS_ESI], esi /* ESI register */ + mov dword ptr cs:[BSS_RegisterSet + REGS_EDI], edi /* EDI register */ + + mov ax, ds /* DS register */ + mov word ptr cs:[BSS_RegisterSet + REGS_DS], ax + mov ax, es /* ES register */ + mov word ptr cs:[BSS_RegisterSet + REGS_ES], ax + mov ax, fs /* FS register */ + mov word ptr cs:[BSS_RegisterSet + REGS_FS], ax + mov ax, gs /* GS register */ + mov word ptr cs:[BSS_RegisterSet + REGS_GS], ax + + pushf + pop dword ptr cs:[BSS_RegisterSet + REGS_EFLAGS] /* EFLAGS register */ + + ret + + + diff --git a/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h b/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h index c6526110183..47854fa9ecf 100644 --- a/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h +++ b/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h @@ -17,11 +17,26 @@ #define DISKREADBUFFER_SIZE 512 /* These addresses specify the realmode "BSS section" layout */ -#define BSS_EntryPoint (BSS_START + 0) +#define BSS_RealModeEntry (BSS_START + 0) #define BSS_CallbackAddress (BSS_START + 4) #define BSS_CallbackReturn (BSS_START + 8) -#define BSS_BootDrive (BSS_START + 12) -#define BSS_BootPartition (BSS_START + 16) + +#define BSS_RegisterSet (BSS_START + 16) /* size = 36 */ +#define BSS_IntVector (BSS_START + 52) +// next 52 + +/* Layout of the REGS structure */ +#define REGS_EAX 0 +#define REGS_EBX 4 +#define REGS_ECX 8 +#define REGS_EDX 12 +#define REGS_ESI 16 +#define REGS_EDI 20 +#define REGS_DS 24 +#define REGS_ES 26 +#define REGS_FS 28 +#define REGS_GS 30 +#define REGS_EFLAGS 32 // Flag Masks