;/** @file | |
; | |
; This code provides low level routines that support the Virtual Machine. | |
; for option ROMs. | |
; | |
; Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> | |
; Copyright (c) 2014 Hewlett-Packard Development Company, L.P.<BR> | |
; 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. | |
; | |
;**/ | |
;--------------------------------------------------------------------------- | |
; Equate files needed. | |
;--------------------------------------------------------------------------- | |
DEFAULT REL | |
SECTION .text | |
extern ASM_PFX(CopyMem) | |
extern ASM_PFX(EbcInterpret) | |
extern ASM_PFX(ExecuteEbcImageEntryPoint) | |
;**************************************************************************** | |
; EbcLLCALLEX | |
; | |
; This function is called to execute an EBC CALLEX instruction. | |
; This instruction requires that we thunk out to external native | |
; code. For x64, we switch stacks, copy the arguments to the stack | |
; and jump to the specified function. | |
; On return, we restore the stack pointer to its original location. | |
; | |
; Destroys no working registers. | |
;**************************************************************************** | |
; INT64 EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr) | |
global ASM_PFX(EbcLLCALLEXNative) | |
ASM_PFX(EbcLLCALLEXNative): | |
push rbp | |
push rbx | |
mov rbp, rsp | |
; Function prolog | |
; Copy FuncAddr to a preserved register. | |
mov rbx, rcx | |
; Set stack pointer to new value | |
sub r8, rdx | |
; | |
; Fix X64 native function call prolog. Prepare space for at least 4 arguments, | |
; even if the native function's arguments are less than 4. | |
; | |
; From MSDN x64 Software Conventions, Overview of x64 Calling Conventions: | |
; "The caller is responsible for allocating space for parameters to the | |
; callee, and must always allocate sufficient space for the 4 register | |
; parameters, even if the callee doesn't have that many parameters. | |
; This aids in the simplicity of supporting C unprototyped functions, | |
; and vararg C/C++ functions." | |
; | |
cmp r8, 0x20 | |
jae skip_expansion | |
mov r8, dword 0x20 | |
skip_expansion: | |
sub rsp, r8 | |
; | |
; Fix X64 native function call 16-byte alignment. | |
; | |
; From MSDN x64 Software Conventions, Stack Usage: | |
; "The stack will always be maintained 16-byte aligned, except within | |
; the prolog (for example, after the return address is pushed)." | |
; | |
and rsp, ~ 0xf | |
mov rcx, rsp | |
sub rsp, 0x20 | |
call ASM_PFX(CopyMem) | |
add rsp, 0x20 | |
; Considering the worst case, load 4 potiential arguments | |
; into registers. | |
mov rcx, qword [rsp] | |
mov rdx, qword [rsp+0x8] | |
mov r8, qword [rsp+0x10] | |
mov r9, qword [rsp+0x18] | |
; Now call the external routine | |
call rbx | |
; Function epilog | |
mov rsp, rbp | |
pop rbx | |
pop rbp | |
ret | |
;**************************************************************************** | |
; EbcLLEbcInterpret | |
; | |
; Begin executing an EBC image. | |
;**************************************************************************** | |
; UINT64 EbcLLEbcInterpret(VOID) | |
global ASM_PFX(EbcLLEbcInterpret) | |
ASM_PFX(EbcLLEbcInterpret): | |
; | |
;; mov rax, ca112ebccall2ebch | |
;; mov r10, EbcEntryPoint | |
;; mov r11, EbcLLEbcInterpret | |
;; jmp r11 | |
; | |
; Caller uses above instruction to jump here | |
; The stack is below: | |
; +-----------+ | |
; | RetAddr | | |
; +-----------+ | |
; |EntryPoint | (R10) | |
; +-----------+ | |
; | Arg1 | <- RDI | |
; +-----------+ | |
; | Arg2 | | |
; +-----------+ | |
; | ... | | |
; +-----------+ | |
; | Arg16 | | |
; +-----------+ | |
; | Dummy | | |
; +-----------+ | |
; | RDI | | |
; +-----------+ | |
; | RSI | | |
; +-----------+ | |
; | RBP | <- RBP | |
; +-----------+ | |
; | RetAddr | <- RSP is here | |
; +-----------+ | |
; | Scratch1 | (RCX) <- RSI | |
; +-----------+ | |
; | Scratch2 | (RDX) | |
; +-----------+ | |
; | Scratch3 | (R8) | |
; +-----------+ | |
; | Scratch4 | (R9) | |
; +-----------+ | |
; | Arg5 | | |
; +-----------+ | |
; | Arg6 | | |
; +-----------+ | |
; | ... | | |
; +-----------+ | |
; | Arg16 | | |
; +-----------+ | |
; | |
; save old parameter to stack | |
mov [rsp + 0x8], rcx | |
mov [rsp + 0x10], rdx | |
mov [rsp + 0x18], r8 | |
mov [rsp + 0x20], r9 | |
; Construct new stack | |
push rbp | |
mov rbp, rsp | |
push rsi | |
push rdi | |
push rbx | |
sub rsp, 0x80 | |
push r10 | |
mov rsi, rbp | |
add rsi, 0x10 | |
mov rdi, rsp | |
add rdi, 8 | |
mov rcx, dword 16 | |
rep movsq | |
; build new paramater calling convention | |
mov r9, [rsp + 0x18] | |
mov r8, [rsp + 0x10] | |
mov rdx, [rsp + 0x8] | |
mov rcx, r10 | |
; call C-code | |
call ASM_PFX(EbcInterpret) | |
add rsp, 0x88 | |
pop rbx | |
pop rdi | |
pop rsi | |
pop rbp | |
ret | |
;**************************************************************************** | |
; EbcLLExecuteEbcImageEntryPoint | |
; | |
; Begin executing an EBC image. | |
;**************************************************************************** | |
; UINT64 EbcLLExecuteEbcImageEntryPoint(VOID) | |
global ASM_PFX(EbcLLExecuteEbcImageEntryPoint) | |
ASM_PFX(EbcLLExecuteEbcImageEntryPoint): | |
; | |
;; mov rax, ca112ebccall2ebch | |
;; mov r10, EbcEntryPoint | |
;; mov r11, EbcLLExecuteEbcImageEntryPoint | |
;; jmp r11 | |
; | |
; Caller uses above instruction to jump here | |
; The stack is below: | |
; +-----------+ | |
; | RetAddr | | |
; +-----------+ | |
; |EntryPoint | (R10) | |
; +-----------+ | |
; |ImageHandle| | |
; +-----------+ | |
; |SystemTable| | |
; +-----------+ | |
; | Dummy | | |
; +-----------+ | |
; | Dummy | | |
; +-----------+ | |
; | RetAddr | <- RSP is here | |
; +-----------+ | |
; |ImageHandle| (RCX) | |
; +-----------+ | |
; |SystemTable| (RDX) | |
; +-----------+ | |
; | |
; build new paramater calling convention | |
mov r8, rdx | |
mov rdx, rcx | |
mov rcx, r10 | |
; call C-code | |
sub rsp, 0x28 | |
call ASM_PFX(ExecuteEbcImageEntryPoint) | |
add rsp, 0x28 | |
ret | |