[FREELDR]

Start implementing a realmode callback mechanism

svn path=/trunk/; revision=52226
This commit is contained in:
Timo Kreuzer
2011-06-14 12:17:28 +00:00
parent 2d003a9075
commit cdd784fd19
4 changed files with 198 additions and 11 deletions
+53 -2
View File
@@ -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
*
@@ -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)
@@ -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
@@ -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