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;---------------------------------------------------------------------------- 42AsmExecute32BitCode 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 110Compatible: 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 139ReturnBack: 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 175ReloadCS: 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 214AsmExecute32BitCode ENDP 215 216 END 217