[FREELDR]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Fri, 26 Aug 2011 09:15:38 +0000 (09:15 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Fri, 26 Aug 2011 09:15:38 +0000 (09:15 +0000)
- Implement switching back to real mode
- use a symbolic name for the size of the REGGS structure

svn path=/trunk/; revision=53451

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

index 9a30d85..4405dfb 100644 (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
index c117aa0..d1f6402 100644 (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
index 4124523..1b1c456 100644 (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:
index 11aef1f..35ea942 100644 (file)
 #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) \
index 7322da6..c7bceab 100644 (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 */
 #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)
 #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 */