[FREELDR] Add support for loading Linux in x64 FreeLdr. Part 1/2: ASM code.
[reactos.git] / boot / freeldr / freeldr / arch / amd64 / entry.S
1
2 #include <asm.inc>
3 #include <arch/pc/x86common.h>
4 #include <arch/pc/pcbios.h>
5
6 EXTERN BootMain:PROC
7 // EXTERN cmdline:DWORD
8
9 EXTERN DiskStopFloppyMotor:PROC
10
11 #ifdef _USE_ML
12 EXTERN __bss_start__:FWORD
13 EXTERN __bss_end__:FWORD
14 #endif
15
16 .code64
17
18 PUBLIC RealEntryPoint
19 RealEntryPoint:
20 /* Setup segment selectors */
21 mov ax, LMODE_DS
22 mov ds, ax
23 mov es, ax
24 mov fs, ax
25 mov gs, ax
26 // mov ss, ax
27
28 //mov word ptr [HEX(b8000)], HEX(0e00) + '1'
29
30 /* Setup long mode stack */
31 mov rsp, qword ptr [stack64]
32
33 /* Continue execution */
34 jmp qword ptr [ContinueAddress]
35
36 ContinueAddress:
37 .quad offset FrldrStartup
38
39 FrldrStartup:
40
41 /* Store BootDrive and BootPartition */
42 mov al, byte ptr [BSS_BootDrive]
43 mov byte ptr [FrldrBootDrive], al
44 xor eax, eax
45 mov al, byte ptr [BSS_BootPartition]
46 mov dword ptr [FrldrBootPartition], eax
47
48 /* Patch long jump with real mode entry point */
49 mov eax, dword ptr [BSS_RealModeEntry]
50 mov dword ptr [AddressOfRealModeEntryPoint], eax
51
52 /* Clean out BSS */
53 xor rax, rax
54 mov rdi, offset __bss_start__
55 mov rcx, offset __bss_end__ + 7
56 sub rcx, rdi
57 shr rcx, 3
58 rep stosq
59
60 /* Pass the command line to BootMain */
61 // mov rcx, offset cmdline
62 xor rcx, rcx
63
64 /* GO! */
65 call BootMain
66
67 /* We should never get here */
68 stop:
69 jmp short stop
70 nop
71 nop
72
73
74 PUBLIC Reboot
75 Reboot:
76 /* Stop the floppy drive motor */
77 call DiskStopFloppyMotor
78
79 /* Set the function ID and switch to real mode (we don't return) */
80 mov bx, FNID_Reboot
81 jmp SwitchToReal
82
83
84 /*
85 * VOID __cdecl Relocator16Boot(
86 * IN REGS* In<rcx>,
87 * IN USHORT StackSegment<dx>,
88 * IN USHORT StackPointer<r8w>,
89 * IN USHORT CodeSegment<r9w>,
90 * IN USHORT CodePointer<rsp+40>);
91 *
92 * RETURNS: Nothing.
93 *
94 * NOTE: The implementation of this function is similar to that of Int386(),
95 * with the proviso that no attempt is done to save the original values of
96 * the registers since we will not need them anyway, as we do not return back
97 * to the caller but instead place the machine in a permanent new CPU state.
98 */
99 PUBLIC Relocator16Boot
100 Relocator16Boot:
101
102 /* Save home registers */
103 mov qword ptr [rsp + 8], rcx
104 mov word ptr [rsp + 16], dx
105 mov word ptr [rsp + 24], r8w
106 mov word ptr [rsp + 32], r9w
107
108 #if 0
109 /* Save non-volatile registers */
110 push rbx
111 push rsi
112 push rdi
113 #endif
114
115 /* Copy input registers */
116 mov rsi, qword ptr [rsp + 8]
117 mov rdi, BSS_RegisterSet
118 mov rcx, REGS_SIZE / 4
119 rep movsd
120
121 /* Set the stack segment/offset */
122 // Since BSS_CallbackReturn contains a ULONG, store in its high word
123 // the stack segment and in its low word the stack offset.
124 mov ax, word ptr [rsp + 16]
125 shl eax, 16
126 mov ax, word ptr [rsp + 24]
127 mov dword ptr [BSS_CallbackReturn], eax
128
129 /*
130 * Set the code segment/offset (Copy entry point)
131 * NOTE: We permanently *ERASE* the contents of ds:[BSS_RealModeEntry]
132 * but it is not a problem since we are going to place the machine in
133 * a permanent new CPU state.
134 */
135 // Since BSS_RealModeEntry contains a ULONG, store in its high word
136 // the code segment and in its low word the code offset.
137 mov ax, word ptr [rsp + 32]
138 shl eax, 16
139 mov ax, word ptr [rsp + 40]
140 mov dword ptr [BSS_RealModeEntry], eax
141
142 /* Set the function ID and switch to real mode (we don't return) */
143 mov bx, FNID_Relocator16Boot
144 jmp SwitchToReal
145
146
147 /*
148 * U16 PxeCallApi(U16 Segment, U16 Offset, U16 Service, VOID *Parameter);
149 *
150 * RETURNS:
151 */
152 PUBLIC PxeCallApi
153 PxeCallApi:
154 xor eax, eax
155 ret
156
157
158 /* Internal function for realmode calls
159 * bx must be set to the ID of the realmode function to call. */
160 PUBLIC CallRealMode
161 CallRealMode:
162 /* Save current stack pointer */
163 mov qword ptr [stack64], rsp
164
165 /* Set continue address and switch to real mode */
166 lea rax, [CallRealMode_return]
167 mov qword ptr [ContinueAddress], rax
168
169 SwitchToReal:
170 /* Set sane segments */
171 mov ax, LMODE_DS
172 mov ds, ax
173 mov es, ax
174 mov fs, ax
175 mov gs, ax
176 //mov ss, ax
177
178 //mov word ptr [HEX(0b8008)], HEX(0e00) + '4'
179
180 /* Save 64-bit stack pointer */
181 mov qword ptr [stack64], rsp
182
183 /* Step 1 - jump to compatibility segment */
184 jmp fword ptr [jumpvector]
185
186 jumpvector:
187 .long offset SwitchToRealCompSegment
188 .word CMODE_CS
189
190 SwitchToRealCompSegment:
191 /* Note: In fact the CPU is in 32 bit mode here. But it will interpret
192 the generated instructions accordingly. rax will become eax */
193
194 /* Step 2 - deactivate long mode, by disabling paging */
195 mov rax, cr0
196 and eax, HEX(7fffffff) //~0x80000000, upper bits cleared
197 mov cr0, rax
198
199 // mov word ptr [HEX(0b800a)], HEX(0e00) + '5'
200
201 /* Step 3 - jump to 16-bit segment to set the limit correctly */
202 .byte HEX(0EA) // 32bit long jmp
203 AddressOfRealModeEntryPoint:
204 .long 0 // receives address of RealModeEntryPoint
205 .word HEX(20)//RMODE_CS
206 nop
207
208 CallRealMode_return:
209 /* restore stack pointer */
210 mov rsp, qword ptr [stack64]
211 ret
212
213 /////////////////////////////////////////
214
215
216 // void __fastfail(unsigned int Code<rcx>);
217 PUBLIC __fastfail
218 __fastfail:
219 // mov ecx, [rsp + 4]
220 int HEX(29)
221
222 // void __lgdt(void *Source<rcx>);
223 PUBLIC __lgdt
224 __lgdt:
225 lgdt fword ptr [rcx]
226 ret
227
228 // void __ltr(unsigned short Source<rcx>);
229 PUBLIC __ltr
230 __ltr:
231 ltr cx
232 ret
233
234 // void _sgdt(void *Destination<rcx>);
235 PUBLIC __sgdt
236 __sgdt:
237 sgdt fword ptr [rcx]
238 ret
239
240
241 /* 64-bit stack pointer */
242 stack64:
243 .quad STACKADDR
244
245 PUBLIC FrldrBootDrive
246 FrldrBootDrive:
247 .byte 0
248
249 PUBLIC FrldrBootPartition
250 FrldrBootPartition:
251 .long 0
252
253 END