• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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