| ;/** @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> | |
| ; 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. | |
| ;--------------------------------------------------------------------------- | |
| ;--------------------------------------------------------------------------- | |
| ; Assembler options | |
| ;--------------------------------------------------------------------------- | |
| SECTION .text | |
| extern ASM_PFX(CopyMem) | |
| extern ASM_PFX(EbcInterpret) | |
| extern ASM_PFX(ExecuteEbcImageEntryPoint) | |
| ;**************************************************************************** | |
| ; EbcLLCALLEXNative | |
| ; | |
| ; This function is called to execute an EBC CALLEX instruction | |
| ; to native code. | |
| ; This instruction requires that we thunk out to external native | |
| ; code. For IA32, we simply switch stacks 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 ebp | |
| push ebx | |
| mov ebp, esp ; standard function prolog | |
| ; Get function address in a register | |
| ; mov ecx, FuncAddr => mov ecx, dword ptr [FuncAddr] | |
| mov ecx, dword [esp + 0xC] | |
| ; Set stack pointer to new value | |
| ; mov eax, NewStackPointer => mov eax, dword ptr [NewSp] | |
| mov eax, dword [esp + 0x14] | |
| mov edx, dword [esp + 0x10] | |
| sub eax, edx | |
| sub esp, eax | |
| mov ebx, esp | |
| push ecx | |
| push eax | |
| push edx | |
| push ebx | |
| call ASM_PFX(CopyMem) | |
| pop eax | |
| pop eax | |
| pop eax | |
| pop ecx | |
| ; Now call the external routine | |
| call ecx | |
| ; ebp is preserved by the callee. In this function it | |
| ; equals the original esp, so set them equal | |
| mov esp, ebp | |
| ; Standard function epilog | |
| mov esp, ebp | |
| pop ebx | |
| pop ebp | |
| ret | |
| ;**************************************************************************** | |
| ; EbcLLEbcInterpret | |
| ; | |
| ; Begin executing an EBC image. | |
| ;**************************************************************************** | |
| ; UINT64 EbcLLEbcInterpret(VOID) | |
| global ASM_PFX(EbcLLEbcInterpret) | |
| ASM_PFX(EbcLLEbcInterpret): | |
| ; | |
| ;; mov eax, 0xca112ebc | |
| ;; mov eax, EbcEntryPoint | |
| ;; mov ecx, EbcLLEbcInterpret | |
| ;; jmp ecx | |
| ; | |
| ; Caller uses above instruction to jump here | |
| ; The stack is below: | |
| ; +-----------+ | |
| ; | RetAddr | | |
| ; +-----------+ | |
| ; |EntryPoint | (EAX) | |
| ; +-----------+ | |
| ; | Arg1 | <- EDI | |
| ; +-----------+ | |
| ; | Arg2 | | |
| ; +-----------+ | |
| ; | ... | | |
| ; +-----------+ | |
| ; | Arg16 | | |
| ; +-----------+ | |
| ; | EDI | | |
| ; +-----------+ | |
| ; | ESI | | |
| ; +-----------+ | |
| ; | EBP | <- EBP | |
| ; +-----------+ | |
| ; | RetAddr | <- ESP is here | |
| ; +-----------+ | |
| ; | Arg1 | <- ESI | |
| ; +-----------+ | |
| ; | Arg2 | | |
| ; +-----------+ | |
| ; | ... | | |
| ; +-----------+ | |
| ; | Arg16 | | |
| ; +-----------+ | |
| ; | |
| ; Construct new stack | |
| push ebp | |
| mov ebp, esp | |
| push esi | |
| push edi | |
| sub esp, 0x40 | |
| push eax | |
| mov esi, ebp | |
| add esi, 8 | |
| mov edi, esp | |
| add edi, 4 | |
| mov ecx, 16 | |
| rep movsd | |
| ; call C-code | |
| call ASM_PFX(EbcInterpret) | |
| add esp, 0x44 | |
| pop edi | |
| pop esi | |
| pop ebp | |
| ret | |
| ;**************************************************************************** | |
| ; EbcLLExecuteEbcImageEntryPoint | |
| ; | |
| ; Begin executing an EBC image. | |
| ;**************************************************************************** | |
| ; UINT64 EbcLLExecuteEbcImageEntryPoint(VOID) | |
| global ASM_PFX(EbcLLExecuteEbcImageEntryPoint) | |
| ASM_PFX(EbcLLExecuteEbcImageEntryPoint): | |
| ; | |
| ;; mov eax, 0xca112ebc | |
| ;; mov eax, EbcEntryPoint | |
| ;; mov ecx, EbcLLExecuteEbcImageEntryPoint | |
| ;; jmp ecx | |
| ; | |
| ; Caller uses above instruction to jump here | |
| ; The stack is below: | |
| ; +-----------+ | |
| ; | RetAddr | | |
| ; +-----------+ | |
| ; |EntryPoint | (EAX) | |
| ; +-----------+ | |
| ; |ImageHandle| | |
| ; +-----------+ | |
| ; |SystemTable| | |
| ; +-----------+ | |
| ; | RetAddr | <- ESP is here | |
| ; +-----------+ | |
| ; |ImageHandle| | |
| ; +-----------+ | |
| ; |SystemTable| | |
| ; +-----------+ | |
| ; | |
| ; Construct new stack | |
| mov [esp - 0xC], eax | |
| mov eax, [esp + 0x4] | |
| mov [esp - 0x8], eax | |
| mov eax, [esp + 0x8] | |
| mov [esp - 0x4], eax | |
| ; call C-code | |
| sub esp, 0xC | |
| call ASM_PFX(ExecuteEbcImageEntryPoint) | |
| add esp, 0xC | |
| ret | |