summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Core/DxeIplX64Peim/x64/LongMode.S
blob: 273b3d5bc22305ca3033487f630bedf30d0a729d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#------------------------------------------------------------------------------
#*
#*   Copyright (c) 2006, Intel Corporation                                                         
#*   All rights reserved. This program and the accompanying materials                          
#*   are licensed and made available under the terms and conditions of the BSD License         
#*   which accompanies this distribution.  The full text of the license may be found at        
#*   http://opensource.org/licenses/bsd-license.php                                            
#*                                                                                             
#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
#*   
#*    LongMode.S
#*  
#*   Abstract:
#*
#*    Transition from 32-bit protected mode EFI environment into x64 
#*    64-bit bit long mode.
#*  
#*   This file is not fully ported or operational.
#*  
#------------------------------------------------------------------------------

.686p: 
#.MODEL flat

#
# Create the exception handler code in IA32 C code
#

.code: 
.stack: 
.MMX: 
.XMM: 

.global _LoadGo64Gdt;
_LoadGo64Gdt:
    pushl   %ebp              # C prolog
    pushl   %edi
    movl    %esp, %ebp
    #
    # Disable interrupts
    #
    cli
    #
    # Reload the selectors
    # Note:
    #      Make the Selectors 64-bit ready
    #
    movl    gdtr, %edi          # Load GDT register
    movw    %cs, %ax            # Get the selector data from our code image          
    mov     %ax, %es
# FIXME MISMATCH: "    lgdt    FWORD PTR es:[edi]  "

    .byte   0x67
    .byte   0xea              # Far Jump Offset:Selector to reload CS
# FIXME MISMATCH: "    dd      OFFSET DataSelectorRld"
# FIXME MISMATCH: "    dw      LINEAR_CODE_SEL   "
DataSelectorRld:
    movw    SYS_DATA_SEL, %ax # Update the Base for the new selectors, too
    movw    %ax, %ds
    movw    %ax, %es
    movw    %ax, %fs
    movw    %ax, %gs
    movw    %ax, %ss

    popl    %edi
    popl    %ebp
    ret
#_LoadGo64Gdt ENDP


# VOID
# ActivateLongMode (
#   IN  EFI_PHYSICAL_ADDRESS  PageTables,  
#   IN  EFI_PHYSICAL_ADDRESS  HobStart,
#   IN  EFI_PHYSICAL_ADDRESS  Stack,
#   IN  EFI_PHYSICAL_ADDRESS  PpisNeededByDxeIplEntryPoint,
#   IN  EFI_PHYSICAL_ADDRESS  DxeCoreEntryPoint
#   )
#
# Input:  [ebp][0h]  = Original ebp
#         [ebp][4h]  = Return address
#         [ebp][8h]  = PageTables
#         [ebp][10h] = HobStart
#         [ebp][18h] = Stack
#         [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer)
#         [ebp][28h] = CodeEntryPoint2 <--- Call this second
#
#
.global _ActivateLongMode;
_ActivateLongMode:
    pushl   %ebp              # C prolog
    movl    %esp, %ebp

    #
    # Use CPUID to determine if the processor supports long mode.
    #
    movl    $0x80000000, %eax # Extended-function code 8000000h.
    cpuid                   # Is largest extended function
    cmpl    $0x80000000, %eax # any function > 80000000h?
    jbe     no_long_mode    # If not, no long mode.
    movl    $0x80000001, %eax # Extended-function code 8000001h.
    cpuid                   # Now EDX = extended-features flags.
    btl     $29, %edx       # Test if long mode is supported.
    jnc     no_long_mode    # Exit if not supported.

    #
    # Enable the 64-bit page-translation-table entries by
    # setting CR4.PAE=1 (this is _required_ before activating
    # long mode). Paging is not enabled until after long mode
    # is enabled.
    #
    movl %cr4, %eax
    btsl $5, %eax
    movl %eax, %cr4

    #
    # Get the long-mode page tables, and initialize the
    # 64-bit CR3 (page-table base address) to point to the base
    # of the PML4 page table. The PML4 page table must be located
    # below 4 Gbytes because only 32 bits of CR3 are loaded when
    # the processor is not in 64-bit mode.
    #
    movl 0x8(%ebp), %eax    # Get Page Tables
    movl %eax, %cr3          # Initialize CR3 with PML4 base.

    #
    # Enable long mode (set EFER.LME=1).
    #
    movl $0xc0000080, %ecx # EFER MSR number.
    rdmsr               # Read EFER.
    btsl $8, %eax       # Set LME=1.
    wrmsr               # Write EFER.

    #
    # Enable paging to activate long mode (set CR0.PG=1)
    #


    movl %cr0, %eax # Read CR0.
    btsl $31, %eax # Set PG=1.
    movl %eax, %cr0 # Write CR0.
    jmp   go_to_long_mode
go_to_long_mode: 

    #
    # This is the next instruction after enabling paging.  Jump to long mode
    #
    .byte   0x67
    .byte   0xea              # Far Jump Offset:Selector to reload CS
#FIXME MISMATCH: "    dd      OFFSET in_long_mode"
#FIXME MISMATCH: "    dw      SYS_CODE64_SEL    "
in_long_mode:
    movw    SYS_DATA64_SEL, %ax
    movw    %ax, %es
    movw    %ax, %ss
    movw    %ax, %ds
    jmp     .


    #
    # We're in long mode, so marshall the arguments to call the
    # passed in function pointers
    # Recall
    #         [ebp][10h] = HobStart
    #         [ebp][18h] = Stack
    #         [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer)
    #         [ebp][28h] = DxeCoreEntryPoint            <--- Call this second
    #
    .byte 0x48
    movl 0x18(%ebp), %ebx     # Setup the stack
    .byte 0x48
    movl %ebx, %esp           # On a new stack now


## 00000905  FF D0                  call rax

    .byte 0x48
    movl 0x10(%ebp), %ecx     # Pass Hob Start in RCX
    .byte 0x48
    movl 0x28(%ebp), %eax     # Get the function pointer for 
                              # DxeCoreEntryPoint into EAX

## 00000905  FF D0                  call rax
    .byte 0xff
    .byte 0xd0

    #
    # WE SHOULD NEVER GET HERE!!!!!!!!!!!!!
    #
no_long_mode: 
    jmp   no_long_mode
#_ActivateLongMode ENDP

        .align 16

gdtr: #FIXME MISMATCH: "gdtr    dw _GDT_END - _GDT_BASE - 1   "
#FIXME MISMATCH: "        dd OFFSET _GDT_BASE          "

#-----------------------------------------------------------------------------;
#   global descriptor table (GDT)
#-----------------------------------------------------------------------------;

        .align 16

.global _GDT_BASE
_GDT_BASE: 
# null descriptor
.equ                NULL_SEL, .-_GDT_BASE     # Selector [0]
        .word 0         # limit 15:0
        .word 0         # base 15:0
        .byte 0         # base 23:16
        .byte 0         # type
        .byte 0         # limit 19:16, flags
        .byte 0         # base 31:24

# linear data segment descriptor
.equ            LINEAR_SEL, .-_GDT_BASE         # Selector [0x8]
        .word 0xFFFF    # limit 0xFFFFF
        .word 0         # base 0
        .byte 0
        .byte 0x92      # present, ring 0, data, expand-up, writable
        .byte 0xCF              # page-granular, 32-bit
        .byte 0

# linear code segment descriptor
.equ            LINEAR_CODE_SEL, .-_GDT_BASE         # Selector [0x10]
        .word 0xFFFF    # limit 0xFFFFF
        .word 0         # base 0
        .byte 0
        .byte 0x9F      # present, ring 0, data, expand-up, writable
        .byte 0xCF              # page-granular, 32-bit
        .byte 0

# system data segment descriptor
.equ            SYS_DATA_SEL, .-_GDT_BASE         # Selector [0x18]
        .word 0xFFFF    # limit 0xFFFFF
        .word 0         # base 0
        .byte 0
        .byte 0x93      # present, ring 0, data, expand-up, writable
        .byte 0xCF              # page-granular, 32-bit
        .byte 0

# system code segment descriptor
.equ            SYS_CODE_SEL, .-_GDT_BASE         # Selector [0x20]
        .word 0xFFFF    # limit 0xFFFFF
        .word 0         # base 0
        .byte 0
        .byte 0x9A      # present, ring 0, data, expand-up, writable
        .byte 0xCF              # page-granular, 32-bit
        .byte 0

# spare segment descriptor
.equ        SPARE3_SEL, .-_GDT_BASE             # Selector [0x28]
        .word 0         # limit 0xFFFFF
        .word 0         # base 0
        .byte 0
        .byte 0         # present, ring 0, data, expand-up, writable
        .byte 0         # page-granular, 32-bit
        .byte 0

#
# system data segment descriptor
#
.equ              SYS_DATA64_SEL, .-_GDT_BASE           # Selector [0x30]
        .word 0xFFFF    # limit 0xFFFFF
        .word 0         # base 0
        .byte 0
        .byte 0x92      # P | DPL [1..2] | 1   | 1   | C | R | A
        .byte 0xCF      # G | D   | L    | AVL | Segment [19..16]
        .byte 0

#
# system code segment descriptor
#
.equ              SYS_CODE64_SEL, .-_GDT_BASE           # Selector [0x38]
        .word 0xFFFF    # limit 0xFFFFF
        .word 0         # base 0
        .byte 0
        .byte 0x9A      # P | DPL [1..2] | 1   | 1   | C | R | A
        .byte 0xAF      # G | D   | L    | AVL | Segment [19..16]
        .byte 0

# spare segment descriptor
.equ        SPARE4_SEL, .-_GDT_BASE             # Selector [0x40]
        .word 0         # limit 0xFFFFF
        .word 0         # base 0
        .byte 0
        .byte 0         # present, ring 0, data, expand-up, writable
        .byte 0         # page-granular, 32-bit
        .byte 0

_GDT_END: