[FREELDR]

- Implement switching back to real mode
- use a symbolic name for the size of the REGGS structure

svn path=/trunk/; revision=53451
This commit is contained in:
Timo Kreuzer 2011-08-26 09:15:38 +00:00
parent b9ae58dc0d
commit 82454038b9
5 changed files with 183 additions and 26 deletions

View file

@ -9,20 +9,118 @@ EXTERN BootMain:PROC
PUBLIC RealEntryPoint
RealEntryPoint:
//mov ax, LMODE_DS
//mov ds, ax
/* Setup segment selectors */
mov ax, LMODE_DS
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
// mov ss, ax
//mov word ptr [HEX(b8000)], HEX(0e00) + '1'
/* Setup long mode stack */
mov rsp, qword ptr [stack64]
/* Continue execution */
jmp qword ptr [ContinueAddress]
ContinueAddress:
.double offset FrldrStartup
FrldrStartup:
/* Store BootDrive and BootPartition */
mov byte ptr [FrldrBootDrive], dl
xor eax, eax
mov al, dh
mov dword ptr [FrldrBootPartition], eax
/* Patch long jump with real mode entry point */
mov eax, dword ptr [BSS_RealModeEntry]
mov dword ptr [AddressOfRealModeEntryPoint], eax
/* GO! */
xor rcx, rcx
call BootMain
/* We should never get here */
stop:
jmp stop
nop
nop
/* Internal function for realmode calls
* bx must be set to the ID of the realmode function to call. */
PUBLIC CallRealMode
CallRealMode:
/* Save current stack pointer */
mov qword ptr [stack64], rsp
/* Set continue address and switch to real mode */
lea rax, [CallRealMode_return]
mov qword ptr [ContinueAddress], rax
SwitchToReal:
/* Set sane segments */
mov ax, LMODE_DS
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
//mov ss, ax
mov word ptr [HEX(0b8008)], HEX(0e00) + '4'
/* Save 64-bit stack pointer */
mov qword ptr [stack64], rsp
/* Step 1 - jump to compatibility segment */
jmp fword ptr [jumpvector]
jumpvector:
.long offset SwitchToRealCompSegment
.word CMODE_CS
SwitchToRealCompSegment:
/* Note: In fact the CPU is in 32 bit mode here. But it will interprete
the generated instructions accordingly. rax will become eax */
/* Step 2 - deactivate long mode, by disabling paging */
mov rax, cr0
and eax, HEX(7fffffff) //~0x80000000, upper bits cleared
mov cr0, rax
// mov word ptr [HEX(0b800a)], HEX(0e00) + '5'
/* Step 3 - jump to 16-bit segment to set the limit correctly */
.byte HEX(0EA) // 32bit long jmp
AddressOfRealModeEntryPoint:
.long 0 // receives address of RealModeEntryPoint
.word HEX(20)//RMODE_CS
nop
CallRealMode_return:
/* restore stack pointer */
mov rsp, qword ptr [stack64]
ret
/////////////////////////////////////////
/* 64-bit stack pointer */
stack64:
.double STACK64ADDR
PUBLIC FrldrBootDrive
FrldrBootDrive:
.byte 0
PUBLIC FrldrBootPartition
FrldrBootPartition:
.long 0
PUBLIC PageDirectoryEnd
PageDirectoryEnd:
@ -34,8 +132,57 @@ PUBLIC PnpBiosGetDeviceNodeCount
PnpBiosGetDeviceNodeCount:
PUBLIC PnpBiosSupported
PnpBiosSupported:
/* int Int386(int ivec<ecx>, REGS* in<rdx>, REGS* out<r8>); */
PUBLIC Int386
Int386:
/* Save home registers */
mov r11, rsp
mov qword ptr [r11 + 8], rcx
mov qword ptr [r11 + 16], rdx
mov qword ptr [r11 + 24], r8
/* Save non-volatile registers */
push rbx
push rbp
push rsi
push rdi
/* Alloc stack space for home registers */
sub rsp, 40
//.ENDPROLOG
mov word ptr [HEX(0b8006)], HEX(0e00) + '3'
/* Copy the int vector to shared memory */
mov dword ptr [BSS_IntVector], ecx
/* Copy input registers */
mov rsi, rdx
mov rdi, BSS_RegisterSet
mov rcx, REGS_SIZE / 4
rep movsd
/* Set the function ID and call real mode */
mov bx, FNID_Int386
call CallRealMode
/* Copy output registers */
mov rsi, BSS_RegisterSet
mov rdi, [r11 + 16]
mov rcx, REGS_SIZE / 4
rep movsd
/* cleanup and return */
add rsp, 40
pop rdi
pop rsi
pop rbp
pop rbx
ret
PUBLIC PxeCallApi
PxeCallApi:
PUBLIC __lgdt

View file

@ -110,7 +110,7 @@ _Int386:
/* Copy input registers */
mov esi, dword ptr [Int386_regsin]
mov edi, BSS_RegisterSet
mov ecx, 9
mov ecx, REGS_SIZE / 4
rep movsd
/* Set the function ID */
@ -125,7 +125,7 @@ Int386_return:
/* Copy output registers */
mov esi, BSS_RegisterSet
mov edi, dword ptr [Int386_regsout]
mov ecx, 9
mov ecx, REGS_SIZE / 4
rep movsd
popa

View file

@ -100,14 +100,14 @@ Msg_LongModeSupported:
Msg_SwitchToLongMode:
.ascii "Switching to long mode....", CR, LF, NUL
.align 4
.align 8
gdt:
.word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 00: NULL descriptor */
.word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 08: */
.word HEX(0000), HEX(0000), HEX(9800), HEX(0020) /* 10: long mode cs */
.word HEX(ffff), HEX(0000), HEX(f300), HEX(00cf) /* 18: long mode ds */
.word HEX(FFFF), HEX(0000), HEX(9E00), HEX(0000) /* 16-bit real mode CS */
.word HEX(FFFF), HEX(0000), HEX(9200), HEX(0000) /* 16-bit real mode DS */
.word HEX(FFFF), HEX(0000), HEX(9E00), HEX(0000) /* 20: 16-bit real mode CS */
.word HEX(FFFF), HEX(0000), HEX(9200), HEX(0000) /* 28: 16-bit real mode DS */
.word HEX(FFFF), HEX(0000), HEX(9B00), HEX(00CF) /* 30: compat mode cs */
/* GDT table pointer */
@ -232,7 +232,20 @@ BuildPageTables:
/* This is the entry point from long mode */
RealModeEntryPoint:
/* Disable Protected Mode */
mov eax, cr0
and eax, HEX(0fffffffe) // ~0x00000001
mov cr0, eax
/* Clear prefetch queue & correct CS */
ljmp16 0, offset InRealMode
InRealMode:
mov ax, HEX(0b800)
mov es, ax
mov word ptr es:[12], HEX(0e00) + '6'
jmp $
ExitToLongMode:

View file

@ -26,12 +26,6 @@
#undef KIP0PCRADDRESS
#define KIP0PCRADDRESS 0xFFFFF78000001000ULL /* FIXME!!! */
#define STACK64ADDR 0x74000 /* The 64-bit stack top will be at 0x74000 */
/* Long mode selectors */
#define LMODE_CS 0x10
#define LMODE_DS 0x18
#define VA_MASK 0x0000FFFFFFFFFFFFUL
#define PtrToPfn(p) \

View file

@ -14,6 +14,7 @@
#define FREELDR_BASE HEX(F800)
#define FREELDR_PE_BASE HEX(10000)
#define STACK32ADDR HEX(98000) /* The 32-bit stack top will be at 9000:8000, or 0xA8000 */
#define STACK64ADDR HEX(98000) /* The 64-bit stack top will be at 98000 */
#define BIOSCALLBUFFER HEX(98000) /* Buffer to store temporary data for any Int386() call */
#define FILESYSBUFFER HEX(80000) /* Buffer to store file system data (e.g. cluster buffer for FAT) */
#define DISKREADBUFFER HEX(90000) /* Buffer to store data read in from the disk via the BIOS */
@ -22,6 +23,20 @@
#define BIOSCALLBUFSEGMENT (BIOSCALLBUFFER/16) /* Buffer to store temporary data for any Int386() call */
#define BIOSCALLBUFOFFSET HEX(0000) /* Buffer to store temporary data for any Int386() call */
/* 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
#define REGS_SIZE 36
/* These addresses specify the realmode "BSS section" layout */
#define BSS_RealModeEntry (BSS_START + 0)
#define BSS_CallbackAddress (BSS_START + 4)
@ -52,19 +67,6 @@
#define FNID_PnpBiosGetDeviceNode 5
#define FNID_BootLinuxKernel 6
/* 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 */
#define CR0_PE_SET HEX(00000001) /* OR this value with CR0 to enable pmode */
#define CR0_PE_CLR HEX(FFFFFFFE) /* AND this value with CR0 to disable pmode */
@ -80,6 +82,7 @@
/* Long mode selectors */
#define LMODE_CS HEX(10)
#define LMODE_DS HEX(18)
#define CMODE_CS HEX(30)
//#endif
/* Makes "x" a global variable or label */