[FREELDR]
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / entry.S
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <asm.inc>
21 #include <arch/pc/x86common.h>
22
23 EXTERN _BootMain:PROC
24 EXTERN _InitIdt:PROC
25 EXTERN _i386Idt:DWORD
26 //EXTERN _i386idtptr:FWORD
27
28 .code32
29
30 PUBLIC _RealEntryPoint
31 _RealEntryPoint:
32
33 /* Setup segment selectors */
34 mov ax, PMODE_DS
35 mov ds, ax
36 mov es, ax
37 mov fs, ax
38 mov gs, ax
39 mov ss, ax
40
41 /* Setup protected mode stack */
42 mov esp, dword ptr [stack32]
43
44 /* Load the IDT */
45 #ifdef _USE_ML
46 lidt fword ptr [i386idtptr]
47 #else
48 lidt i386idtptr
49 #endif
50
51 /* Continue execution */
52 jmp dword ptr [ContinueAddress]
53
54 ContinueAddress:
55 .long _FrldrStartup
56
57
58 _FrldrStartup:
59
60 /* Store BootDrive and BootPartition */
61 xor eax, eax
62 mov al, dl
63 mov dword ptr [_FrldrBootDrive], eax
64 mov al, dh
65 mov dword ptr [_FrldrBootPartition], eax
66
67 /* Patch long jump with real mode entry point */
68 mov eax, dword ptr ds:[BSS_RealModeEntry]
69 mov dword ptr ds:[SwitchToReal16Address], eax
70
71 /* Initialize the idt */
72 call _InitIdt
73
74 /* GO! */
75 xor eax, eax
76 push eax
77 call _BootMain
78
79 /* We should never get here */
80 stop:
81 jmp stop
82 nop
83 nop
84
85 #ifndef _USE_ML
86 /*
87 * Switches the processor to protected mode
88 * it destroys eax
89 */
90 EXTERN(switch_to_prot)
91
92 .code16
93
94 cli /* None of these */
95
96 /* We don't know what values are currently */
97 /* in the segment registers. So we are */
98 /* going to reload them with sane values. */
99 /* Of course CS has to already be valid. */
100 /* We are currently in real-mode so we */
101 /* need real-mode segment values. */
102 xor ax, ax
103 mov ds, ax
104 mov es, ax
105 mov fs, ax
106 mov gs, ax
107 mov ss, ax
108
109 /* Get the return address off the stack */
110 pop word ptr ds:[code32ret]
111
112 /* Save 16-bit stack pointer */
113 mov word ptr ds:[stack16], sp
114
115 /* Load the GDT */
116 lgdt gdtptr
117
118 /* Load the IDT */
119 lidt i386idtptr
120
121 /* Enable Protected Mode */
122 mov eax, cr0
123 or eax, CR0_PE_SET
124 mov cr0, eax
125
126 /* Clear prefetch queue & correct CS */
127 //ljmp PMODE_CS, inpmode
128 jmp far ptr PMODE_CS:inpmode
129
130 .code32
131
132 inpmode:
133 /* Setup segment selectors */
134 mov ax, PMODE_DS
135 mov ds, ax
136 mov es, ax
137 mov fs, ax
138 mov gs, ax
139 mov ss, ax
140 mov esp, dword ptr [stack32]
141
142 /* Put the return address back onto the stack */
143 push dword ptr [code32ret]
144
145 /* Now return in p-mode! */
146 ret
147
148 /*
149 * Switches the processor back to real mode
150 * it destroys eax
151 */
152 EXTERN(switch_to_real)
153
154 .code32
155
156 /* We don't know what values are currently */
157 /* in the segment registers. So we are */
158 /* going to reload them with sane values. */
159 /* Of course CS has to already be valid. */
160 /* We are currently in protected-mode so we */
161 /* need protected-mode segment values. */
162 mov ax, PMODE_DS
163 mov ds, ax
164 mov es, ax
165 mov fs, ax
166 mov gs, ax
167 mov ss, ax
168
169 /* Get the return address off the stack */
170 pop dword ptr [code16ret]
171
172 /* Save 32-bit stack pointer */
173 mov dword ptr [stack32], esp
174
175 /* jmp to 16-bit segment to set the limit correctly */
176 ljmp RMODE_CS, switch_to_real16
177
178 switch_to_real16:
179 .code16
180
181 /* Restore segment registers to correct limit */
182 mov ax, RMODE_DS
183 mov ds, ax
184 mov es, ax
185 mov fs, ax
186 mov gs, ax
187 mov ss, ax
188
189 /* Disable Protected Mode */
190 mov eax, cr0
191 and eax, CR0_PE_CLR
192 mov cr0, eax
193
194 /* Clear prefetch queue & correct CS */
195 //ljmp $0, $inrmode
196 jmp far ptr 0:inrmode
197
198 inrmode:
199 mov ax, cs
200 mov ds, ax
201 mov es, ax
202 mov fs, ax
203 mov gs, ax
204 mov ss, ax
205
206 /* Clear out the high 16-bits of ESP */
207 /* This is needed because I have one */
208 /* machine that hangs when booted to dos if */
209 /* anything other than 0x0000 is in the high */
210 /* 16-bits of ESP. Even though real-mode */
211 /* code should only use SP and not ESP. */
212 xor esp, esp
213
214 mov sp, word ptr ds:[stack16]
215
216 /* Put the return address back onto the stack */
217 push word ptr ds:[code16ret]
218
219 /* Load IDTR with real mode value */
220 lidt rmode_idtptr
221
222 sti /* These are ok now */
223
224 /* Now return in r-mode! */
225 ret
226 #endif
227
228 .code32
229
230 Int386_regsin:
231 .long 0
232 Int386_regsout:
233 .long 0
234
235 /*
236 * int Int386(int ivec, REGS* in, REGS* out);
237 */
238 PUBLIC _Int386
239 _Int386:
240
241 /* Get the function parameters */
242 mov eax, dword ptr [esp + 4]
243 mov dword ptr ds:[BSS_IntVector], eax
244 mov eax, dword ptr [esp + 8]
245 mov dword ptr [Int386_regsin], eax
246 mov eax, dword ptr [esp + 12]
247 mov dword ptr [Int386_regsout], eax
248
249 /* Save all registers + segment registers */
250 push ds
251 push es
252 push fs
253 push gs
254 pusha
255
256 /* Copy input registers */
257 mov esi, dword ptr [Int386_regsin]
258 mov edi, BSS_RegisterSet
259 mov ecx, 9
260 rep movsd
261
262 /* Set the function ID */
263 mov bx, FNID_Int386
264
265 /* Set continue address and switch to real mode */
266 mov dword ptr [ContinueAddress], offset Int386_return
267 jmp SwitchToReal
268
269 Int386_return:
270
271 /* Copy output registers */
272 mov esi, BSS_RegisterSet
273 mov edi, dword ptr [Int386_regsout]
274 mov ecx, 9
275 rep movsd
276
277 popa
278 pop gs
279 pop fs
280 pop es
281 pop ds
282 ret
283
284
285 /*
286 * U16 PxeCallApi(U16 Segment, U16 Offset, U16 Service, VOID *Parameter);
287 *
288 * RETURNS:
289 */
290 PUBLIC _PxeCallApi
291 _PxeCallApi:
292 push ebp
293 mov ebp, esp
294
295 pusha
296 push es
297
298 /* copy entry point */
299 mov eax, [ebp + 8]
300 shl eax, 16
301 mov ax, [ebp + 12]
302 mov dword ptr ds:[BSS_PxeEntryPoint], eax
303
304 /* copy function */
305 mov ax, [ebp + 16]
306 mov word ptr ds:[BSS_PxeFunction], ax
307
308 /* convert pointer to data buffer to segment/offset */
309 mov eax, [ebp + 20]
310 shr eax, 4
311 and eax, HEX(0f000)
312 mov word ptr ds:[BSS_PxeBufferSegment], ax
313 mov eax, [ebp + 20]
314 and eax, HEX(0ffff)
315 mov word ptr ds:[BSS_PxeBufferOffset], ax
316
317 /* Set the function ID and call realmode */
318 mov bx, FNID_PxeCallApi
319 call i386CallRealMode
320
321 pop es
322 popa
323
324 mov esp, ebp
325 pop ebp
326
327 mov ax, word ptr [BSS_PxeResult]
328
329 ret
330
331
332 PUBLIC _SoftReboot
333 _SoftReboot:
334 /* Set the function ID */
335 mov bx, FNID_SoftReboot
336
337 /*Switch to real mode (We don't return) */
338 jmp SwitchToReal
339
340
341 PUBLIC _ChainLoadBiosBootSectorCode
342 _ChainLoadBiosBootSectorCode:
343 /* Set the boot drive */
344 mov dl, byte ptr [_FrldrBootDrive]
345
346 /* Set the function ID */
347 mov bx, FNID_ChainLoadBiosBootSectorCode
348
349 /*Switch to real mode (We don't return) */
350 jmp SwitchToReal
351
352
353 PUBLIC i386CallRealMode
354 i386CallRealMode:
355 /* Set continue address and switch to real mode */
356 mov dword ptr [ContinueAddress], offset i386CallRealMode_return
357 jmp SwitchToReal
358 i386CallRealMode_return:
359 ret
360
361
362 /* Entrypoint for realmode function calls
363 * ContinueAddress must be set to the return point from realmode
364 * bx must be set to the ID of the realmode function to call. */
365 SwitchToReal:
366 /* Set sane segments */
367 mov ax, PMODE_DS
368 mov ds, ax
369 mov es, ax
370 mov fs, ax
371 mov gs, ax
372 mov ss, ax
373
374 /* Save 32-bit stack pointer */
375 mov dword ptr [stack32], esp
376
377 /* jmp to 16-bit segment to set the limit correctly */
378 .byte HEX(0ea) // jmp far RMODE_CS:switch_to_real16
379 SwitchToReal16Address:
380 .long 0 // receives address of switch_to_real16
381 .word RMODE_CS
382 nop
383
384
385 /* 16-bit stack pointer */
386 stack16:
387 .word STACK16ADDR
388
389 /* 32-bit stack pointer */
390 stack32:
391 .long STACK32ADDR
392
393 /* 16-bit return address */
394 code16ret:
395 .long 0
396
397 /* 32-bit return address */
398 code32ret:
399 .long 0
400
401
402 .align 4 /* force 4-byte alignment */
403 gdt:
404 /* NULL Descriptor */
405 .word HEX(0000)
406 .word HEX(0000)
407 .word HEX(0000)
408 .word HEX(0000)
409
410 /* 32-bit flat CS */
411 .word HEX(FFFF)
412 .word HEX(0000)
413 .word HEX(9A00)
414 .word HEX(00CF)
415
416 /* 32-bit flat DS */
417 .word HEX(FFFF)
418 .word HEX(0000)
419 .word HEX(9200)
420 .word HEX(00CF)
421
422 /* 16-bit real mode CS */
423 .word HEX(FFFF)
424 .word HEX(0000)
425 .word HEX(9E00)
426 .word HEX(0000)
427
428 /* 16-bit real mode DS */
429 .word HEX(FFFF)
430 .word HEX(0000)
431 .word HEX(9200)
432 .word HEX(0000)
433
434 /* GDT table pointer */
435 gdtptr:
436 .word HEX(27) /* Limit */
437 .long gdt /* Base Address */
438
439 /* Real-mode IDT pointer */
440 rmode_idtptr:
441 .word HEX(3ff) /* Limit */
442 .long 0 /* Base Address */
443
444 PUBLIC i386idtptr
445 i386idtptr:
446 .word 255 /* Limit */
447 .long _i386Idt /* Base Address */
448
449 PUBLIC _FrldrBootDrive
450 _FrldrBootDrive:
451 .long 0
452
453 PUBLIC _FrldrBootPartition
454 _FrldrBootPartition:
455 .long 0
456
457 END