]> git.sur5r.net Git - u-boot/blob - arch/x86/lib/realmode_switch.S
Merge branch 'master' of git://git.denx.de/u-boot-x86
[u-boot] / arch / x86 / lib / realmode_switch.S
1 /*
2  * (C) Copyright 2002
3  * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
4  *
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
24 /* 32bit -> 16bit -> 32bit mode switch code */
25
26 /*
27  * Stack frame at 0xe00
28  *      e00 ebx;
29  *      e04 ecx;
30  *      e08 edx;
31  *      e0c esi;
32  *      e10 edi;
33  *      e14 ebp;
34  *      e18 eax;
35  *      e1c ds;
36  *      e20 es;
37  *      e24 fs;
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 */
48 #define o32             .byte 0x66;     /* operand size prefix 32 */
49
50 .section .realmode, "ax"
51 .code16
52
53         /* 16bit protected mode code here */
54 .globl realmode_enter
55 realmode_enter:
56 o32     pusha
57 o32     pushf
58         cli
59         sidt    saved_idt
60         sgdt    saved_gdt
61         movl    %esp, %eax
62         movl    %eax, saved_protected_mode_esp
63
64         movl    $0x10, %eax
65         movl    %eax, %esp
66         movw    $0x28, %ax
67         movw    %ax, %ds
68         movw    %ax, %es
69         movw    %ax, %fs
70         movw    %ax, %gs
71
72         lidt    realmode_idt_ptr
73         /* Go back into real mode by clearing PE to 0 */
74         movl    %cr0, %eax
75         andl    $0x7ffffffe, %eax
76         movl    %eax, %cr0
77
78         /* switch to real mode */
79         ljmp    $0x0,$do_realmode
80
81 do_realmode:
82         /* realmode code from here */
83         movw    %cs,%ax
84         movw    %ax,%ds
85         movw    %ax,%es
86         movw    %ax,%fs
87         movw    %ax,%gs
88
89         /* create a temporary stack */
90         movw    $0xc0, %ax
91         movw    %ax, %ss
92         movw    $0x200, %ax
93         movw    %ax, %sp
94
95         popl    %ebx
96         popl    %ecx
97         popl    %edx
98         popl    %esi
99         popl    %edi
100         popl    %ebp
101         popl    %eax
102         movl    %eax, temp_eax
103         popl    %eax
104         movw    %ax, %ds
105         popl    %eax
106         movw    %ax, %es
107         popl    %eax
108         movw    %ax, %fs
109         popl    %eax
110         movw    %ax, %gs
111         popl    %eax                            /* orig_eax */
112         popl    %eax
113 cs      movw    %ax, temp_ip
114         popl    %eax
115 cs      movw    %ax, temp_cs
116 o32     popf
117         popl    %eax
118         popw    %ss
119         movl    %eax, %esp
120 cs      movl    temp_eax, %eax
121
122         /* self-modifying code, better flush the cache */
123         wbinvd
124
125         .byte   0x9a                            /* lcall */
126 temp_ip:
127         .word   0                               /* new ip */
128 temp_cs:
129         .word   0                               /* new cs */
130
131 realmode_ret:
132         /* save eax, esp and ss */
133 cs      movl    %eax, saved_eax
134         movl    %esp, %eax
135 cs      movl    %eax, saved_esp
136         movw    %ss, %ax
137 cs      movw    %ax, saved_ss
138
139         /*
140          * restore the stack, note that we set sp to 0x244;
141          * pt_regs is 0x44 bytes long and we push the structure
142          * backwards on to the stack, bottom first
143          */
144         movw    $0xc0, %ax
145         movw    %ax, %ss
146         movw    $0x244, %ax
147         movw    %ax, %sp
148
149         xorl    %eax,%eax
150 cs      movw    saved_ss, %ax
151         pushl   %eax
152 cs      movl    saved_esp, %eax
153         pushl   %eax
154 o32     pushf
155         xorl    %eax,%eax
156 cs      movw    temp_cs, %ax
157         pushl   %eax
158 cs      movw    temp_ip, %ax
159         pushl   %eax
160         pushl   $0
161         movw    %gs, %ax
162         pushl   %eax
163         movw    %fs, %ax
164         pushl   %eax
165         movw    %es, %ax
166         pushl   %eax
167         movw    %ds, %ax
168         pushl   %eax
169         movl    saved_eax, %eax
170         pushl   %eax
171         pushl   %ebp
172         pushl   %edi
173         pushl   %esi
174         pushl   %edx
175         pushl   %ecx
176         pushl   %ebx
177
178 o32 cs  lidt    saved_idt
179 o32 cs  lgdt    saved_gdt
180
181         /* Go back into protected mode reset PE to 1 */
182         movl    %cr0, %eax
183         orl     $1,%eax
184         movl    %eax, %cr0
185
186         /* flush prefetch queue */
187         jmp     next_line
188 next_line:
189         movw    $return_ptr, %ax
190         movw    %ax,%bp
191 o32 cs  ljmp    *(%bp)
192
193 .code32
194 protected_mode:
195         /* Reload segment registers */
196         movl    $0x18, %eax
197         movw    %ax, %fs
198         movw    %ax, %ds
199         movw    %ax, %gs
200         movw    %ax, %es
201         movw    %ax, %ss
202         movl    saved_protected_mode_esp, %eax
203         movl    %eax, %esp
204         popf
205         popa
206         ret
207
208 temp_eax:
209         .long   0
210
211 saved_ss:
212         .word   0
213 saved_esp:
214         .long   0
215 saved_eax:
216         .long   0
217
218 realmode_idt_ptr:
219         .word   0x400
220         .word   0x0, 0x0
221
222 saved_gdt:
223         .word   0, 0, 0, 0
224 saved_idt:
225         .word   0, 0, 0, 0
226
227 saved_protected_mode_esp:
228         .long   0
229
230 return_ptr:
231         .long   protected_mode
232         .word   0x10