1 ; 2 ; Copyright (c) 2010, Intel Corporation. All rights reserved.<BR> 3 ; This program and the accompanying materials 4 ; are licensed and made available under the terms and conditions of the BSD License 5 ; which accompanies this distribution. The full text of the license may be found at 6 ; http://opensource.org/licenses/bsd-license.php 7 ; 8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 10 ; 11 ; 12 ; Module Name: 13 ; 14 ; AsmDispatchExecute.asm 15 ; 16 ; Abstract: 17 ; 18 ; This is the assembly code to transition from long mode to compatibility mode to execute 32-bit code and then 19 ; transit back to long mode. 20 ; 21 ;------------------------------------------------------------------------------- 22 .code 23 ;---------------------------------------------------------------------------- 24 ; Procedure: AsmExecute32BitCode 25 ; 26 ; Input: None 27 ; 28 ; Output: None 29 ; 30 ; Prototype: EFI_STATUS 31 ; AsmExecute32BitCode ( 32 ; IN UINT64 Function, 33 ; IN UINT64 Param1, 34 ; IN UINT64 Param2, 35 ; IN IA32_DESCRIPTOR *InternalGdtr 36 ; ); 37 ; 38 ; 39 ; Description: A thunk function to execute 32-bit code in long mode. 40 ; 41 ;---------------------------------------------------------------------------- 42 AsmExecute32BitCode PROC 43 ; 44 ; save orignal GDTR and CS 45 ; 46 mov rax, ds 47 push rax 48 mov rax, cs 49 push rax 50 sub rsp, 10h 51 sgdt fword ptr [rsp] 52 ; 53 ; load internal GDT 54 ; 55 lgdt fword ptr [r9] 56 ; 57 ; Save general purpose register and rflag register 58 ; 59 pushfq 60 push rdi 61 push rsi 62 push rbp 63 push rbx 64 65 ; 66 ; save CR3 67 ; 68 mov rax, cr3 69 mov rbp, rax 70 71 ; 72 ; Prepare the CS and return address for the transition from 32-bit to 64-bit mode 73 ; 74 mov rax, 10h ; load long mode selector 75 shl rax, 32 76 mov r9, OFFSET ReloadCS ;Assume the ReloadCS is under 4G 77 or rax, r9 78 push rax 79 ; 80 ; Save parameters for 32-bit function call 81 ; 82 mov rax, r8 83 shl rax, 32 84 or rax, rdx 85 push rax 86 ; 87 ; save the 32-bit function entry and the return address into stack which will be 88 ; retrieve in compatibility mode. 89 ; 90 mov rax, OFFSET ReturnBack ;Assume the ReloadCS is under 4G 91 shl rax, 32 92 or rax, rcx 93 push rax 94 95 ; 96 ; let rax save DS 97 ; 98 mov rax, 018h 99 100 ; 101 ; Change to Compatible Segment 102 ; 103 mov rcx, 08h ; load compatible mode selector 104 shl rcx, 32 105 mov rdx, OFFSET Compatible ; assume address < 4G 106 or rcx, rdx 107 push rcx 108 retf 109 110 Compatible: 111 ; reload DS/ES/SS to make sure they are correct referred to current GDT 112 mov ds, ax 113 mov es, ax 114 mov ss, ax 115 116 ; 117 ; Disable paging 118 ; 119 mov rcx, cr0 120 btc ecx, 31 121 mov cr0, rcx 122 ; 123 ; Clear EFER.LME 124 ; 125 mov ecx, 0C0000080h 126 rdmsr 127 btc eax, 8 128 wrmsr 129 130 ; Now we are in protected mode 131 ; 132 ; Call 32-bit function. Assume the function entry address and parameter value is less than 4G 133 ; 134 pop rax ; Here is the function entry 135 ; 136 ; Now the parameter is at the bottom of the stack, then call in to IA32 function. 137 ; 138 jmp rax 139 ReturnBack: 140 pop rcx ; drop param1 141 pop rcx ; drop param2 142 143 ; 144 ; restore CR4 145 ; 146 mov rax, cr4 147 bts eax, 5 148 mov cr4, rax 149 150 ; 151 ; restore CR3 152 ; 153 mov eax, ebp 154 mov cr3, rax 155 156 ; 157 ; Set EFER.LME to re-enable ia32-e 158 ; 159 mov ecx, 0C0000080h 160 rdmsr 161 bts eax, 8 162 wrmsr 163 ; 164 ; Enable paging 165 ; 166 mov rax, cr0 167 bts eax, 31 168 mov cr0, rax 169 ; Now we are in compatible mode 170 171 ; 172 ; Reload cs register 173 ; 174 retf 175 ReloadCS: 176 ; 177 ; Now we're in Long Mode 178 ; 179 ; 180 ; Restore C register and eax hold the return status from 32-bit function. 181 ; Note: Do not touch rax from now which hold the return value from IA32 function 182 ; 183 pop rbx 184 pop rbp 185 pop rsi 186 pop rdi 187 popfq 188 ; 189 ; Switch to orignal GDT and CS. here rsp is pointer to the orignal GDT descriptor. 190 ; 191 lgdt fword ptr[rsp] 192 ; 193 ; drop GDT descriptor in stack 194 ; 195 add rsp, 10h 196 ; 197 ; switch to orignal CS and GDTR 198 ; 199 pop r9 ; get CS 200 shl r9, 32 ; rcx[32..47] <- Cs 201 mov rcx, OFFSET @F 202 or rcx, r9 203 push rcx 204 retf 205 @@: 206 ; 207 ; Reload original DS/ES/SS 208 ; 209 pop rcx 210 mov ds, rcx 211 mov es, rcx 212 mov ss, rcx 213 ret 214 AsmExecute32BitCode ENDP 215 216 END 217