]>
Commit | Line | Data |
---|---|---|
2262cfee WD |
1 | /* |
2 | * (C) Copyright 2002 | |
fa82f871 | 3 | * Daniel Engström, Omicron Ceti AB, daniel@omicron.se |
8bde7f77 | 4 | * |
2262cfee WD |
5 | * See file CREDITS for list of people who contributed to this |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
2262cfee WD |
24 | /* 32bit -> 16bit -> 32bit mode switch code */ |
25 | ||
26 | /* | |
27 | * Stack frame at 0xe00 | |
53677ef1 | 28 | * e00 ebx; |
2262cfee WD |
29 | * e04 ecx; |
30 | * e08 edx; | |
31 | * e0c esi; | |
32 | * e10 edi; | |
8bde7f77 | 33 | * e14 ebp; |
2262cfee | 34 | * e18 eax; |
8bde7f77 | 35 | * e1c ds; |
2262cfee | 36 | * e20 es; |
8bde7f77 | 37 | * e24 fs; |
2262cfee WD |
38 | * e28 gs; |
39 | * e2c orig_eax; | |
40 | * e30 eip; | |
41 | * e34 cs; | |
42 | * e38 eflags; | |
43 | * e3c esp; | |
44 | * e40 ss; | |
45 | */ | |
46 | ||
47 | #define a32 .byte 0x67; /* address size prefix 32 */ | |
8bde7f77 | 48 | #define o32 .byte 0x66; /* operand size prefix 32 */ |
2262cfee WD |
49 | |
50 | .section .realmode, "ax" | |
51 | .code16 | |
2262cfee WD |
52 | /* 16bit protected mode code here */ |
53 | .globl realmode_enter | |
54 | realmode_enter: | |
55 | o32 pusha | |
56 | o32 pushf | |
57 | cli | |
53677ef1 WD |
58 | sidt saved_idt |
59 | sgdt saved_gdt | |
60 | movl %esp, %eax | |
61 | movl %eax, saved_protected_mode_esp | |
8bde7f77 | 62 | |
2262cfee | 63 | movl $0x10, %eax |
53677ef1 | 64 | movl %eax, %esp |
2262cfee WD |
65 | movw $0x28, %ax |
66 | movw %ax, %ds | |
67 | movw %ax, %es | |
68 | movw %ax, %fs | |
69 | movw %ax, %gs | |
70 | ||
71 | lidt realmode_idt_ptr | |
53677ef1 WD |
72 | movl %cr0, %eax /* Go back into real mode by */ |
73 | andl $0x7ffffffe, %eax /* clearing PE to 0 */ | |
2262cfee | 74 | movl %eax, %cr0 |
53677ef1 | 75 | ljmp $0x0,$do_realmode /* switch to real mode */ |
8bde7f77 WD |
76 | |
77 | do_realmode: /* realmode code from here */ | |
2262cfee WD |
78 | movw %cs,%ax |
79 | movw %ax,%ds | |
80 | movw %ax,%es | |
81 | movw %ax,%fs | |
82 | movw %ax,%gs | |
8bde7f77 | 83 | |
2262cfee | 84 | /* create a temporary stack */ |
8bde7f77 WD |
85 | |
86 | movw $0xc0, %ax | |
87 | movw %ax, %ss | |
88 | movw $0x200, %ax | |
89 | movw %ax, %sp | |
90 | ||
2262cfee WD |
91 | popl %ebx |
92 | popl %ecx | |
93 | popl %edx | |
94 | popl %esi | |
95 | popl %edi | |
96 | popl %ebp | |
97 | popl %eax | |
98 | movl %eax, temp_eax | |
99 | popl %eax | |
100 | movw %ax, %ds | |
101 | popl %eax | |
102 | movw %ax, %es | |
103 | popl %eax | |
104 | movw %ax, %fs | |
105 | popl %eax | |
106 | movw %ax, %gs | |
107 | popl %eax /* orig_eax */ | |
108 | popl %eax | |
109 | cs movw %ax, temp_ip | |
110 | popl %eax | |
111 | cs movw %ax, temp_cs | |
112 | o32 popf | |
113 | popl %eax | |
114 | popw %ss | |
115 | movl %eax, %esp | |
116 | cs movl temp_eax, %eax | |
53677ef1 | 117 | wbinvd /* self-modifying code, |
2262cfee | 118 | * better flush the cache */ |
8bde7f77 | 119 | |
2262cfee WD |
120 | .byte 0x9a /* lcall */ |
121 | temp_ip: | |
53677ef1 | 122 | .word 0 /* new ip */ |
8bde7f77 | 123 | temp_cs: |
53677ef1 | 124 | .word 0 /* new cs */ |
2262cfee WD |
125 | realmode_ret: |
126 | /* save eax, esp and ss */ | |
127 | cs movl %eax, saved_eax | |
128 | movl %esp, %eax | |
129 | cs movl %eax, saved_esp | |
53677ef1 | 130 | movw %ss, %ax |
2262cfee | 131 | cs movw %ax, saved_ss |
8bde7f77 | 132 | |
2262cfee WD |
133 | /* restore the stack, note that we set sp to 0x244; |
134 | * pt_regs is 0x44 bytes long and we push the structure | |
135 | * backwards on to the stack, bottom first */ | |
8bde7f77 WD |
136 | |
137 | movw $0xc0, %ax | |
138 | movw %ax, %ss | |
139 | movw $0x244, %ax | |
140 | movw %ax, %sp | |
141 | ||
2262cfee WD |
142 | xorl %eax,%eax |
143 | cs movw saved_ss, %ax | |
144 | pushl %eax | |
145 | cs movl saved_esp, %eax | |
146 | pushl %eax | |
147 | o32 pushf | |
148 | xorl %eax,%eax | |
149 | cs movw temp_cs, %ax | |
150 | pushl %eax | |
151 | cs movw temp_ip, %ax | |
152 | pushl %eax | |
153 | pushl $0 | |
154 | movw %gs, %ax | |
155 | pushl %eax | |
156 | movw %fs, %ax | |
157 | pushl %eax | |
158 | movw %es, %ax | |
159 | pushl %eax | |
160 | movw %ds, %ax | |
161 | pushl %eax | |
162 | movl saved_eax, %eax | |
163 | pushl %eax | |
164 | pushl %ebp | |
165 | pushl %edi | |
166 | pushl %esi | |
167 | pushl %edx | |
168 | pushl %ecx | |
169 | pushl %ebx | |
170 | ||
171 | o32 cs lidt saved_idt | |
53677ef1 | 172 | o32 cs lgdt saved_gdt /* Set GDTR */ |
2262cfee | 173 | |
53677ef1 WD |
174 | movl %cr0, %eax /* Go back into protected mode */ |
175 | orl $1,%eax /* reset PE to 1 */ | |
176 | movl %eax, %cr0 | |
177 | jmp next_line /* flush prefetch queue */ | |
8bde7f77 WD |
178 | next_line: |
179 | movw $return_ptr, %ax | |
53677ef1 | 180 | movw %ax,%bp |
2262cfee WD |
181 | o32 cs ljmp *(%bp) |
182 | ||
183 | .code32 | |
184 | protected_mode: | |
53677ef1 WD |
185 | movl $0x18,%eax /* reload GDT[3] */ |
186 | movw %ax,%fs /* reset FS */ | |
187 | movw %ax,%ds /* reset DS */ | |
188 | movw %ax,%gs /* reset GS */ | |
189 | movw %ax,%es /* reset ES */ | |
190 | movw %ax,%ss /* reset SS */ | |
191 | movl saved_protected_mode_esp, %eax | |
2262cfee WD |
192 | movl %eax, %esp |
193 | popf | |
194 | popa | |
8bde7f77 | 195 | ret |
2262cfee WD |
196 | |
197 | temp_eax: | |
198 | .long 0 | |
199 | ||
200 | saved_ss: | |
53677ef1 | 201 | .word 0 |
2262cfee WD |
202 | saved_esp: |
203 | .long 0 | |
204 | saved_eax: | |
205 | .long 0 | |
8bde7f77 | 206 | |
2262cfee | 207 | realmode_idt_ptr: |
8bde7f77 WD |
208 | .word 0x400 |
209 | .word 0x0, 0x0 | |
210 | ||
211 | saved_gdt: | |
53677ef1 | 212 | .word 0, 0, 0, 0 |
2262cfee | 213 | saved_idt: |
53677ef1 | 214 | .word 0, 0, 0, 0 |
2262cfee WD |
215 | |
216 | saved_protected_mode_esp: | |
53677ef1 | 217 | .long 0 |
8bde7f77 | 218 | |
2262cfee WD |
219 | return_ptr: |
220 | .long protected_mode | |
221 | .word 0x10 |