[FREELDR]
[reactos.git] / reactos / boot / freeldr / freeldr / arch / realmode / i386.S
1
2 #include <asm.inc>
3 #include "../../include/arch/pc/x86common.h"
4
5 #define IMAGE_DOS_HEADER_e_lfanew 60
6 #define IMAGE_FILE_HEADER_SIZE 20
7 #define IMAGE_OPTIONAL_HEADER_AddressOfEntryPoint 16
8
9 .code16
10
11 /* fat helper code */
12 #include "fathelp.inc"
13
14 .org 512
15 RealModeEntryPoint:
16
17 cli
18
19 /* Setup segment registers */
20 xor ax, ax
21 mov ds, ax
22 mov es, ax
23 mov fs, ax
24 mov gs, ax
25 mov ss, ax
26
27 /* Setup the stack */
28 mov sp, word ptr ds:[stack16]
29
30 /* Enable A20 address line */
31 call EnableA20
32
33 /* Safe real mode entry point in shared memory */
34 mov dword ptr ds:[BSS_RealModeEntry], offset switch_to_real16
35
36 /* Get address of optional header */
37 mov eax, dword ptr ds:[FREELDR_PE_BASE + IMAGE_DOS_HEADER_e_lfanew]
38 add eax, FREELDR_PE_BASE + 4 + IMAGE_FILE_HEADER_SIZE
39
40 /* Get address of entry point */
41 mov eax, dword ptr ds:[eax + IMAGE_OPTIONAL_HEADER_AddressOfEntryPoint]
42 add eax, FREELDR_PE_BASE
43
44 /* Save entry point */
45 mov dword ptr ds:[pm_entrypoint], eax
46
47 jmp exit_to_protected
48
49
50 /* This is the entry point from protected mode */
51 switch_to_real16:
52
53 /* Restore segment registers to correct limit */
54 mov ax, RMODE_DS
55 mov ds, ax
56 mov es, ax
57 mov fs, ax
58 mov gs, ax
59 mov ss, ax
60
61 /* Disable Protected Mode */
62 mov eax, cr0
63 and eax, CR0_PE_CLR
64 mov cr0, eax
65
66 /* Clear prefetch queue & correct CS */
67 ljmp16 0, inrmode
68
69 inrmode:
70 /* Set real mode segments */
71 xor ax, ax
72 mov ds, ax
73 mov es, ax
74 mov fs, ax
75 mov gs, ax
76 mov ss, ax
77
78 /* Clear out the high 16-bits of ESP */
79 /* This is needed because I have one */
80 /* machine that hangs when booted to dos if */
81 /* anything other than 0x0000 is in the high */
82 /* 16-bits of ESP. Even though real-mode */
83 /* code should only use SP and not ESP. */
84 xor esp, esp
85
86 /* Restore real mode stack */
87 mov sp, word ptr ds:[stack16]
88
89 /* Load IDTR with real mode value */
90 #ifdef _USE_ML
91 lidt fword ptr rmode_idtptr
92 #else
93 lidt rmode_idtptr
94 #endif
95
96 sti /* These are ok now */
97
98 /* Do the callback, specified by bx */
99 shl bx, 1
100 call word ptr ds:callback_table[bx]
101
102
103 /*
104 * Switches the processor to protected mode
105 * it destroys eax
106 */
107 exit_to_protected:
108
109 cli
110
111 /* Safe current stack pointer */
112 mov word ptr ds:[stack16], sp
113
114 /* Load the GDT */
115 #ifdef _USE_ML
116 lgdt fword ptr gdtptr
117 #else
118 lgdt gdtptr
119 #endif
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 ljmp16 PMODE_CS, inpmode
128 inpmode:
129 .byte HEX(0ff), HEX(25) // opcode of indirect jump
130 .word pm_entrypoint, 0
131 pm_entrypoint:
132 .long 0 // receives address of PE entry point
133 nop
134
135 callback_table:
136 .word Int386
137 .word SoftReboot
138 .word ChainLoadBiosBootSectorCode
139 .word PxeCallApi
140 .word PnpBiosGetDeviceNodeCount
141 .word PnpBiosGetDeviceNode
142 .word BootLinuxKernel
143
144
145 /* 16-bit stack pointer */
146 stack16:
147 .word STACK16ADDR
148
149
150 .align 4 /* force 4-byte alignment */
151 gdt:
152 /* NULL Descriptor */
153 .word HEX(0000)
154 .word HEX(0000)
155 .word HEX(0000)
156 .word HEX(0000)
157
158 /* 32-bit flat CS */
159 .word HEX(FFFF)
160 .word HEX(0000)
161 .word HEX(9A00)
162 .word HEX(00CF)
163
164 /* 32-bit flat DS */
165 .word HEX(FFFF)
166 .word HEX(0000)
167 .word HEX(9200)
168 .word HEX(00CF)
169
170 /* 16-bit real mode CS */
171 .word HEX(FFFF)
172 .word HEX(0000)
173 .word HEX(9E00)
174 .word HEX(0000)
175
176 /* 16-bit real mode DS */
177 .word HEX(FFFF)
178 .word HEX(0000)
179 .word HEX(9200)
180 .word HEX(0000)
181
182 /* GDT table pointer */
183 gdtptr:
184 .word HEX(27) /* Limit */
185 .word gdt, 0 /* Base Address */
186
187 /* Real-mode IDT pointer */
188 rmode_idtptr:
189 .word HEX(3ff) /* Limit */
190 .long 0 /* Base Address */
191
192 #include "int386.inc"
193 #include "pxe.inc"
194 #include "pnp.inc"
195 #include "linux.inc"
196 #include "helpers.inc"
197
198 .org (FREELDR_PE_BASE - FREELDR_BASE - 1)
199 .byte 0
200 .endcode16
201 END