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