1;/** @file 2; 3; This code provides low level routines that support the Virtual Machine. 4; for option ROMs. 5; 6; Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> 7; Copyright (c) 2014 Hewlett-Packard Development Company, L.P.<BR> 8; This program and the accompanying materials 9; are licensed and made available under the terms and conditions of the BSD License 10; which accompanies this distribution. The full text of the license may be found at 11; http://opensource.org/licenses/bsd-license.php 12; 13; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 14; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 15; 16;**/ 17 18;--------------------------------------------------------------------------- 19; Equate files needed. 20;--------------------------------------------------------------------------- 21 22DEFAULT REL 23SECTION .text 24 25extern ASM_PFX(CopyMem) 26extern ASM_PFX(EbcInterpret) 27extern ASM_PFX(ExecuteEbcImageEntryPoint) 28 29;**************************************************************************** 30; EbcLLCALLEX 31; 32; This function is called to execute an EBC CALLEX instruction. 33; This instruction requires that we thunk out to external native 34; code. For x64, we switch stacks, copy the arguments to the stack 35; and jump to the specified function. 36; On return, we restore the stack pointer to its original location. 37; 38; Destroys no working registers. 39;**************************************************************************** 40; INT64 EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr) 41global ASM_PFX(EbcLLCALLEXNative) 42ASM_PFX(EbcLLCALLEXNative): 43 push rbp 44 push rbx 45 mov rbp, rsp 46 ; Function prolog 47 48 ; Copy FuncAddr to a preserved register. 49 mov rbx, rcx 50 51 ; Set stack pointer to new value 52 sub r8, rdx 53 54 ; 55 ; Fix X64 native function call prolog. Prepare space for at least 4 arguments, 56 ; even if the native function's arguments are less than 4. 57 ; 58 ; From MSDN x64 Software Conventions, Overview of x64 Calling Conventions: 59 ; "The caller is responsible for allocating space for parameters to the 60 ; callee, and must always allocate sufficient space for the 4 register 61 ; parameters, even if the callee doesn't have that many parameters. 62 ; This aids in the simplicity of supporting C unprototyped functions, 63 ; and vararg C/C++ functions." 64 ; 65 cmp r8, 0x20 66 jae skip_expansion 67 mov r8, dword 0x20 68skip_expansion: 69 70 sub rsp, r8 71 72 ; 73 ; Fix X64 native function call 16-byte alignment. 74 ; 75 ; From MSDN x64 Software Conventions, Stack Usage: 76 ; "The stack will always be maintained 16-byte aligned, except within 77 ; the prolog (for example, after the return address is pushed)." 78 ; 79 and rsp, ~ 0xf 80 81 mov rcx, rsp 82 sub rsp, 0x20 83 call ASM_PFX(CopyMem) 84 add rsp, 0x20 85 86 ; Considering the worst case, load 4 potiential arguments 87 ; into registers. 88 mov rcx, qword [rsp] 89 mov rdx, qword [rsp+0x8] 90 mov r8, qword [rsp+0x10] 91 mov r9, qword [rsp+0x18] 92 93 ; Now call the external routine 94 call rbx 95 96 ; Function epilog 97 mov rsp, rbp 98 pop rbx 99 pop rbp 100 ret 101 102;**************************************************************************** 103; EbcLLEbcInterpret 104; 105; Begin executing an EBC image. 106;**************************************************************************** 107; UINT64 EbcLLEbcInterpret(VOID) 108global ASM_PFX(EbcLLEbcInterpret) 109ASM_PFX(EbcLLEbcInterpret): 110 ; 111 ;; mov rax, ca112ebccall2ebch 112 ;; mov r10, EbcEntryPoint 113 ;; mov r11, EbcLLEbcInterpret 114 ;; jmp r11 115 ; 116 ; Caller uses above instruction to jump here 117 ; The stack is below: 118 ; +-----------+ 119 ; | RetAddr | 120 ; +-----------+ 121 ; |EntryPoint | (R10) 122 ; +-----------+ 123 ; | Arg1 | <- RDI 124 ; +-----------+ 125 ; | Arg2 | 126 ; +-----------+ 127 ; | ... | 128 ; +-----------+ 129 ; | Arg16 | 130 ; +-----------+ 131 ; | Dummy | 132 ; +-----------+ 133 ; | RDI | 134 ; +-----------+ 135 ; | RSI | 136 ; +-----------+ 137 ; | RBP | <- RBP 138 ; +-----------+ 139 ; | RetAddr | <- RSP is here 140 ; +-----------+ 141 ; | Scratch1 | (RCX) <- RSI 142 ; +-----------+ 143 ; | Scratch2 | (RDX) 144 ; +-----------+ 145 ; | Scratch3 | (R8) 146 ; +-----------+ 147 ; | Scratch4 | (R9) 148 ; +-----------+ 149 ; | Arg5 | 150 ; +-----------+ 151 ; | Arg6 | 152 ; +-----------+ 153 ; | ... | 154 ; +-----------+ 155 ; | Arg16 | 156 ; +-----------+ 157 ; 158 159 ; save old parameter to stack 160 mov [rsp + 0x8], rcx 161 mov [rsp + 0x10], rdx 162 mov [rsp + 0x18], r8 163 mov [rsp + 0x20], r9 164 165 ; Construct new stack 166 push rbp 167 mov rbp, rsp 168 push rsi 169 push rdi 170 push rbx 171 sub rsp, 0x80 172 push r10 173 mov rsi, rbp 174 add rsi, 0x10 175 mov rdi, rsp 176 add rdi, 8 177 mov rcx, dword 16 178 rep movsq 179 180 ; build new paramater calling convention 181 mov r9, [rsp + 0x18] 182 mov r8, [rsp + 0x10] 183 mov rdx, [rsp + 0x8] 184 mov rcx, r10 185 186 ; call C-code 187 call ASM_PFX(EbcInterpret) 188 add rsp, 0x88 189 pop rbx 190 pop rdi 191 pop rsi 192 pop rbp 193 ret 194 195;**************************************************************************** 196; EbcLLExecuteEbcImageEntryPoint 197; 198; Begin executing an EBC image. 199;**************************************************************************** 200; UINT64 EbcLLExecuteEbcImageEntryPoint(VOID) 201global ASM_PFX(EbcLLExecuteEbcImageEntryPoint) 202ASM_PFX(EbcLLExecuteEbcImageEntryPoint): 203 ; 204 ;; mov rax, ca112ebccall2ebch 205 ;; mov r10, EbcEntryPoint 206 ;; mov r11, EbcLLExecuteEbcImageEntryPoint 207 ;; jmp r11 208 ; 209 ; Caller uses above instruction to jump here 210 ; The stack is below: 211 ; +-----------+ 212 ; | RetAddr | 213 ; +-----------+ 214 ; |EntryPoint | (R10) 215 ; +-----------+ 216 ; |ImageHandle| 217 ; +-----------+ 218 ; |SystemTable| 219 ; +-----------+ 220 ; | Dummy | 221 ; +-----------+ 222 ; | Dummy | 223 ; +-----------+ 224 ; | RetAddr | <- RSP is here 225 ; +-----------+ 226 ; |ImageHandle| (RCX) 227 ; +-----------+ 228 ; |SystemTable| (RDX) 229 ; +-----------+ 230 ; 231 232 ; build new paramater calling convention 233 mov r8, rdx 234 mov rdx, rcx 235 mov rcx, r10 236 237 ; call C-code 238 sub rsp, 0x28 239 call ASM_PFX(ExecuteEbcImageEntryPoint) 240 add rsp, 0x28 241 ret 242 243