]>
Commit | Line | Data |
---|---|---|
3219f974 | 1 | #------------------------------------------------------------------------------ |
2 | #* | |
3 | #* Copyright (c) 2006, Intel Corporation | |
4 | #* All rights reserved. This program and the accompanying materials | |
5 | #* are licensed and made available under the terms and conditions of the BSD License | |
6 | #* which accompanies this distribution. The full text of the license may be found at | |
7 | #* http://opensource.org/licenses/bsd-license.php | |
8 | #* | |
9 | #* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
10 | #* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
11 | #* | |
12 | #* LongMode.S | |
13 | #* | |
14 | #* Abstract: | |
15 | #* | |
16 | #* Transition from 32-bit protected mode EFI environment into x64 | |
17 | #* 64-bit bit long mode. | |
18 | #* | |
19 | #* This file is not fully ported or operational. | |
20 | #* | |
21 | #------------------------------------------------------------------------------ | |
22 | ||
23 | .686p: | |
24 | #.MODEL flat | |
25 | ||
26 | # | |
27 | # Create the exception handler code in IA32 C code | |
28 | # | |
29 | ||
30 | .code: | |
31 | .stack: | |
32 | .MMX: | |
33 | .XMM: | |
34 | ||
35 | .global _LoadGo64Gdt; | |
36 | _LoadGo64Gdt: | |
37 | pushl %ebp # C prolog | |
38 | pushl %edi | |
39 | movl %esp, %ebp | |
40 | # | |
41 | # Disable interrupts | |
42 | # | |
43 | cli | |
44 | # | |
45 | # Reload the selectors | |
46 | # Note: | |
47 | # Make the Selectors 64-bit ready | |
48 | # | |
49 | movl gdtr, %edi # Load GDT register | |
50 | movw %cs, %ax # Get the selector data from our code image | |
51 | mov %ax, %es | |
52 | # FIXME MISMATCH: " lgdt FWORD PTR es:[edi] " | |
53 | ||
54 | .byte 0x67 | |
55 | .byte 0xea # Far Jump Offset:Selector to reload CS | |
56 | # FIXME MISMATCH: " dd OFFSET DataSelectorRld" | |
57 | # FIXME MISMATCH: " dw LINEAR_CODE_SEL " | |
58 | DataSelectorRld: | |
59 | movw SYS_DATA_SEL, %ax # Update the Base for the new selectors, too | |
60 | movw %ax, %ds | |
61 | movw %ax, %es | |
62 | movw %ax, %fs | |
63 | movw %ax, %gs | |
64 | movw %ax, %ss | |
65 | ||
66 | popl %edi | |
67 | popl %ebp | |
68 | ret | |
69 | #_LoadGo64Gdt ENDP | |
70 | ||
71 | ||
72 | # VOID | |
73 | # ActivateLongMode ( | |
74 | # IN EFI_PHYSICAL_ADDRESS PageTables, | |
75 | # IN EFI_PHYSICAL_ADDRESS HobStart, | |
76 | # IN EFI_PHYSICAL_ADDRESS Stack, | |
77 | # IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint, | |
78 | # IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint | |
79 | # ) | |
80 | # | |
81 | # Input: [ebp][0h] = Original ebp | |
82 | # [ebp][4h] = Return address | |
83 | # [ebp][8h] = PageTables | |
84 | # [ebp][10h] = HobStart | |
85 | # [ebp][18h] = Stack | |
86 | # [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer) | |
87 | # [ebp][28h] = CodeEntryPoint2 <--- Call this second | |
88 | # | |
89 | # | |
90 | .global _ActivateLongMode; | |
91 | _ActivateLongMode: | |
92 | pushl %ebp # C prolog | |
93 | movl %esp, %ebp | |
94 | ||
95 | # | |
96 | # Use CPUID to determine if the processor supports long mode. | |
97 | # | |
98 | movl $0x80000000, %eax # Extended-function code 8000000h. | |
99 | cpuid # Is largest extended function | |
100 | cmpl $0x80000000, %eax # any function > 80000000h? | |
101 | jbe no_long_mode # If not, no long mode. | |
102 | movl $0x80000001, %eax # Extended-function code 8000001h. | |
103 | cpuid # Now EDX = extended-features flags. | |
104 | btl $29, %edx # Test if long mode is supported. | |
105 | jnc no_long_mode # Exit if not supported. | |
106 | ||
107 | # | |
108 | # Enable the 64-bit page-translation-table entries by | |
109 | # setting CR4.PAE=1 (this is _required_ before activating | |
110 | # long mode). Paging is not enabled until after long mode | |
111 | # is enabled. | |
112 | # | |
113 | movl %cr4, %eax | |
114 | btsl $5, %eax | |
115 | movl %eax, %cr4 | |
116 | ||
117 | # | |
118 | # Get the long-mode page tables, and initialize the | |
119 | # 64-bit CR3 (page-table base address) to point to the base | |
120 | # of the PML4 page table. The PML4 page table must be located | |
121 | # below 4 Gbytes because only 32 bits of CR3 are loaded when | |
122 | # the processor is not in 64-bit mode. | |
123 | # | |
124 | movl 0x8(%ebp), %eax # Get Page Tables | |
125 | movl %eax, %cr3 # Initialize CR3 with PML4 base. | |
126 | ||
127 | # | |
128 | # Enable long mode (set EFER.LME=1). | |
129 | # | |
130 | movl $0xc0000080, %ecx # EFER MSR number. | |
131 | rdmsr # Read EFER. | |
132 | btsl $8, %eax # Set LME=1. | |
133 | wrmsr # Write EFER. | |
134 | ||
135 | # | |
136 | # Enable paging to activate long mode (set CR0.PG=1) | |
137 | # | |
138 | ||
139 | ||
140 | movl %cr0, %eax # Read CR0. | |
141 | btsl $31, %eax # Set PG=1. | |
142 | movl %eax, %cr0 # Write CR0. | |
143 | jmp go_to_long_mode | |
144 | go_to_long_mode: | |
145 | ||
146 | # | |
147 | # This is the next instruction after enabling paging. Jump to long mode | |
148 | # | |
149 | .byte 0x67 | |
150 | .byte 0xea # Far Jump Offset:Selector to reload CS | |
151 | #FIXME MISMATCH: " dd OFFSET in_long_mode" | |
152 | #FIXME MISMATCH: " dw SYS_CODE64_SEL " | |
153 | in_long_mode: | |
154 | movw SYS_DATA64_SEL, %ax | |
155 | movw %ax, %es | |
156 | movw %ax, %ss | |
157 | movw %ax, %ds | |
158 | jmp . | |
159 | ||
160 | ||
161 | # | |
162 | # We're in long mode, so marshall the arguments to call the | |
163 | # passed in function pointers | |
164 | # Recall | |
165 | # [ebp][10h] = HobStart | |
166 | # [ebp][18h] = Stack | |
167 | # [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer) | |
168 | # [ebp][28h] = DxeCoreEntryPoint <--- Call this second | |
169 | # | |
170 | .byte 0x48 | |
171 | movl 0x18(%ebp), %ebx # Setup the stack | |
172 | .byte 0x48 | |
173 | movl %ebx, %esp # On a new stack now | |
174 | ||
175 | ||
176 | ## 00000905 FF D0 call rax | |
177 | ||
178 | .byte 0x48 | |
179 | movl 0x10(%ebp), %ecx # Pass Hob Start in RCX | |
180 | .byte 0x48 | |
181 | movl 0x28(%ebp), %eax # Get the function pointer for | |
182 | # DxeCoreEntryPoint into EAX | |
183 | ||
184 | ## 00000905 FF D0 call rax | |
185 | .byte 0xff | |
186 | .byte 0xd0 | |
187 | ||
188 | # | |
189 | # WE SHOULD NEVER GET HERE!!!!!!!!!!!!! | |
190 | # | |
191 | no_long_mode: | |
192 | jmp no_long_mode | |
193 | #_ActivateLongMode ENDP | |
194 | ||
195 | .align 16 | |
196 | ||
197 | gdtr: #FIXME MISMATCH: "gdtr dw _GDT_END - _GDT_BASE - 1 " | |
198 | #FIXME MISMATCH: " dd OFFSET _GDT_BASE " | |
199 | ||
200 | #-----------------------------------------------------------------------------; | |
201 | # global descriptor table (GDT) | |
202 | #-----------------------------------------------------------------------------; | |
203 | ||
204 | .align 16 | |
205 | ||
206 | .global _GDT_BASE | |
207 | _GDT_BASE: | |
208 | # null descriptor | |
209 | .equ NULL_SEL, .-_GDT_BASE # Selector [0] | |
210 | .word 0 # limit 15:0 | |
211 | .word 0 # base 15:0 | |
212 | .byte 0 # base 23:16 | |
213 | .byte 0 # type | |
214 | .byte 0 # limit 19:16, flags | |
215 | .byte 0 # base 31:24 | |
216 | ||
217 | # linear data segment descriptor | |
218 | .equ LINEAR_SEL, .-_GDT_BASE # Selector [0x8] | |
219 | .word 0xFFFF # limit 0xFFFFF | |
220 | .word 0 # base 0 | |
221 | .byte 0 | |
222 | .byte 0x92 # present, ring 0, data, expand-up, writable | |
223 | .byte 0xCF # page-granular, 32-bit | |
224 | .byte 0 | |
225 | ||
226 | # linear code segment descriptor | |
227 | .equ LINEAR_CODE_SEL, .-_GDT_BASE # Selector [0x10] | |
228 | .word 0xFFFF # limit 0xFFFFF | |
229 | .word 0 # base 0 | |
230 | .byte 0 | |
231 | .byte 0x9F # present, ring 0, data, expand-up, writable | |
232 | .byte 0xCF # page-granular, 32-bit | |
233 | .byte 0 | |
234 | ||
235 | # system data segment descriptor | |
236 | .equ SYS_DATA_SEL, .-_GDT_BASE # Selector [0x18] | |
237 | .word 0xFFFF # limit 0xFFFFF | |
238 | .word 0 # base 0 | |
239 | .byte 0 | |
240 | .byte 0x93 # present, ring 0, data, expand-up, writable | |
241 | .byte 0xCF # page-granular, 32-bit | |
242 | .byte 0 | |
243 | ||
244 | # system code segment descriptor | |
245 | .equ SYS_CODE_SEL, .-_GDT_BASE # Selector [0x20] | |
246 | .word 0xFFFF # limit 0xFFFFF | |
247 | .word 0 # base 0 | |
248 | .byte 0 | |
249 | .byte 0x9A # present, ring 0, data, expand-up, writable | |
250 | .byte 0xCF # page-granular, 32-bit | |
251 | .byte 0 | |
252 | ||
253 | # spare segment descriptor | |
254 | .equ SPARE3_SEL, .-_GDT_BASE # Selector [0x28] | |
255 | .word 0 # limit 0xFFFFF | |
256 | .word 0 # base 0 | |
257 | .byte 0 | |
258 | .byte 0 # present, ring 0, data, expand-up, writable | |
259 | .byte 0 # page-granular, 32-bit | |
260 | .byte 0 | |
261 | ||
262 | # | |
263 | # system data segment descriptor | |
264 | # | |
265 | .equ SYS_DATA64_SEL, .-_GDT_BASE # Selector [0x30] | |
266 | .word 0xFFFF # limit 0xFFFFF | |
267 | .word 0 # base 0 | |
268 | .byte 0 | |
269 | .byte 0x92 # P | DPL [1..2] | 1 | 1 | C | R | A | |
270 | .byte 0xCF # G | D | L | AVL | Segment [19..16] | |
271 | .byte 0 | |
272 | ||
273 | # | |
274 | # system code segment descriptor | |
275 | # | |
276 | .equ SYS_CODE64_SEL, .-_GDT_BASE # Selector [0x38] | |
277 | .word 0xFFFF # limit 0xFFFFF | |
278 | .word 0 # base 0 | |
279 | .byte 0 | |
280 | .byte 0x9A # P | DPL [1..2] | 1 | 1 | C | R | A | |
281 | .byte 0xAF # G | D | L | AVL | Segment [19..16] | |
282 | .byte 0 | |
283 | ||
284 | # spare segment descriptor | |
285 | .equ SPARE4_SEL, .-_GDT_BASE # Selector [0x40] | |
286 | .word 0 # limit 0xFFFFF | |
287 | .word 0 # base 0 | |
288 | .byte 0 | |
289 | .byte 0 # present, ring 0, data, expand-up, writable | |
290 | .byte 0 # page-granular, 32-bit | |
291 | .byte 0 | |
292 | ||
293 | _GDT_END: | |
294 | ||
295 | ||
296 |