[ros-diffs] [tkreuzer] 53451: [FREELDR] - Implement switching back to real mode - use a symbolic name for the size of the REGGS structure

tkreuzer at svn.reactos.org tkreuzer at svn.reactos.org
Fri Aug 26 09:15:42 UTC 2011


Author: tkreuzer
Date: Fri Aug 26 09:15:38 2011
New Revision: 53451

URL: http://svn.reactos.org/svn/reactos?rev=53451&view=rev
Log:
[FREELDR]
- Implement switching back to real mode
- use a symbolic name for the size of the REGGS structure

Modified:
    trunk/reactos/boot/freeldr/freeldr/arch/amd64/entry.S
    trunk/reactos/boot/freeldr/freeldr/arch/i386/entry.S
    trunk/reactos/boot/freeldr/freeldr/arch/realmode/amd64.S
    trunk/reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h
    trunk/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h

Modified: trunk/reactos/boot/freeldr/freeldr/arch/amd64/entry.S
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/arch/amd64/entry.S?rev=53451&r1=53450&r2=53451&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/arch/amd64/entry.S [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/arch/amd64/entry.S [iso-8859-1] Fri Aug 26 09:15:38 2011
@@ -9,20 +9,118 @@
 
 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 @@
 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

Modified: trunk/reactos/boot/freeldr/freeldr/arch/i386/entry.S
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/arch/i386/entry.S?rev=53451&r1=53450&r2=53451&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/arch/i386/entry.S [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/arch/i386/entry.S [iso-8859-1] Fri Aug 26 09:15:38 2011
@@ -110,7 +110,7 @@
     /* 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 @@
     /* Copy output registers */
     mov esi, BSS_RegisterSet
     mov edi, dword ptr [Int386_regsout]
-    mov ecx, 9
+    mov ecx, REGS_SIZE / 4
     rep movsd
 
     popa

Modified: trunk/reactos/boot/freeldr/freeldr/arch/realmode/amd64.S
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/arch/realmode/amd64.S?rev=53451&r1=53450&r2=53451&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/arch/realmode/amd64.S [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/arch/realmode/amd64.S [iso-8859-1] Fri Aug 26 09:15:38 2011
@@ -100,14 +100,14 @@
 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 @@
 
 /* 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:

Modified: trunk/reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h?rev=53451&r1=53450&r2=53451&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/arch/amd64/amd64.h [iso-8859-1] Fri Aug 26 09:15:38 2011
@@ -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) \

Modified: trunk/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h?rev=53451&r1=53450&r2=53451&view=diff
==============================================================================
--- trunk/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h [iso-8859-1] (original)
+++ trunk/reactos/boot/freeldr/freeldr/include/arch/pc/x86common.h [iso-8859-1] Fri Aug 26 09:15:38 2011
@@ -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 */
@@ -21,6 +22,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)
@@ -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 */




More information about the Ros-diffs mailing list