f3e80840b3ef6240952899b2a513f927a7ff9f9c
[mirror_edk2.git] / MdePkg / Library / BaseLib / X64 / Thunk16.asm
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 ; Module Name:
13 ;
14 ; Thunk.asm
15 ;
16 ; Abstract:
17 ;
18 ; Real mode thunk
19 ;
20 ;------------------------------------------------------------------------------
21
22 .data
23
24 NullSegSel DQ 0
25 _16CsSegSel LABEL QWORD
26 DW -1
27 DW 0
28 DB 0
29 DB 9bh
30 DB 8fh ; 16-bit segment
31 DB 0
32 _16BitDsSel LABEL QWORD
33 DW -1
34 DW 0
35 DB 0
36 DB 93h
37 DB 8fh ; 16-bit segment
38 DB 0
39 GdtEnd LABEL QWORD
40
41 .const
42
43 _16Gdtr LABEL FWORD
44 DW offset GdtEnd - offset NullSegSel - 1
45 DQ offset NullSegSel
46
47 _16Idtr FWORD (1 SHL 10) - 1
48
49 .code
50
51 IA32_REGS STRUC 4t
52 _EDI DD ?
53 _ESI DD ?
54 _EBP DD ?
55 _ESP DD ?
56 _EBX DD ?
57 _EDX DD ?
58 _ECX DD ?
59 _EAX DD ?
60 _DS DW ?
61 _ES DW ?
62 _FS DW ?
63 _GS DW ?
64 _RFLAGS DQ ?
65 _EIP DD ?
66 _CS DW ?
67 _SS DW ?
68 IA32_REGS ENDS
69
70 InternalAsmThunk16 PROC USES rbp rbx rsi rdi r12 r13 r14 r15
71 mov eax, ds
72 push rax
73 mov eax, es
74 push rax
75 push fs
76 push gs
77 mov rsi, rcx ; rsi <- RegSet
78 push sizeof (IA32_REGS)
79 pop rcx
80 movzx r8, (IA32_REGS ptr [rsi])._SS
81 xor rdi, rdi
82 mov edi, (IA32_REGS ptr [rsi])._ESP
83 sub rdi, rcx ; reserve space on realmode stack
84 push rdi ; save stack offset
85 imul rax, r8, 16
86 add rdi, rax ; rdi <- linear address of 16-bit stack
87 rep movsb ; copy RegSet
88 mov rsi, r8 ; si <- 16-bit stack segment
89 pop rbx ; rbx <- 16-bit stack offset
90 mov rdi, rdx ; rdi <- realmode patch
91 lea eax, @BackToThunk ; rax <- address to back from real mode
92 push rax ; use in a far return
93 mov eax, cs
94 mov [rsp + 4], eax ; save CS
95 lea eax, @16Return ; thus @Return must < 4GB
96 stosd ; set ret address offset
97 xor eax, eax
98 stosw ; set ret CS base to 0
99 mov eax, esp
100 stosd ; rsp must < 4GB
101 mov eax, ss
102 stosd
103 mov rax, cr0
104 mov ecx, eax ; ecx <- CR0
105 and ecx, 7ffffffeh ; clear PE, PG bits
106 stosd
107 mov rax, cr4
108 mov ebp, eax
109 and ebp, 300h ; clear all but PCE and OSFXSR bits
110 stosd
111 sidt fword ptr [rsp + 70h] ; use parameter space to save IDTR
112 sgdt fword ptr [rdi]
113 lea edi, _16Idtr
114 lea eax, @16Start ; rax <- seg:offset of @16Start
115 push rax
116 mov dword ptr [rsp + 4], 8
117 push 10h
118 pop rax ; rax <- 10h as dataseg selector
119 lgdt _16Gdtr
120 retf
121 @16Start: ; 16-bit starts here
122 mov ss, eax ; set SS to be a 16-bit segment
123 mov cr0, rcx ; disable protected mode
124 mov cr4, rbp
125 DB 66h
126 mov ecx, 0c0000080h
127 rdmsr
128 and ah, NOT 1 ; clear LME
129 wrmsr
130 mov ss, esi ; set up 16-bit stack
131 mov sp, bx ; mov esp, ebx actually
132 lidt fword ptr [edi]
133 DB 66h, 61h ; popad
134 DB 1fh ; pop ds
135 DB 7 ; pop es
136 pop fs
137 pop gs
138 add sp, 8 ; skip _RFLAGS
139 DB 66h
140 retf ; transfer control to 16-bit code
141 @16Return:
142 DB 66h
143 push 0 ; high order 32 bits of rflags
144 pushf ; pushfd actually
145 push gs
146 push fs
147 DB 6 ; push es
148 DB 1eh ; push ds
149 DB 66h, 60h ; pushad
150 DB 67h, 66h, 0c5h, 74h, 24h, 30h ; lds esi, [esp + 12*4]
151 DB 66h
152 mov eax, [esi + 12]
153 mov cr4, rax ; restore CR4
154 DB 66h
155 lgdt fword ptr [esi + 16]
156 DB 66h
157 mov ecx, 0c0000080h
158 rdmsr
159 or ah, 1 ; set LME
160 wrmsr
161 DB 66h
162 mov eax, [esi + 8]
163 mov cr0, rax ; restore CR0
164 xor ax, ax ; xor eax, eax actually
165 mov eax, ss
166 mov dword ptr (IA32_REGS ptr [esp])._SS, eax
167 shl ax, 4 ; shl eax, 4 actually
168 add ax, sp ; add eax, esp actually
169 add sp, sizeof (IA32_REGS) ; add esp, sizeof (IA32_REGS)
170 DB 66h
171 mov dword ptr (IA32_REGS ptr [esp - sizeof (IA32_REGS)])._ESP, esp
172 DB 66h
173 lss esp, fword ptr [esi] ; restore protected mode stack
174 DB 66h
175 retf ; go back to protected mode
176 @BackToThunk:
177 lidt fword ptr [rsp + 68h] ; restore protected mode IDTR
178 shl rax, 32
179 shr rax, 32 ; clear high order 32 bits of RAX
180 pop gs
181 pop fs
182 pop rcx
183 mov es, ecx
184 pop rcx
185 mov ds, ecx
186 ret
187 InternalAsmThunk16 ENDP
188
189 END