]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Foundation/Library/Thunk16/x86Thunk.c
Renamed remotely
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Thunk16 / x86Thunk.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12
13 Module Name:
14
15 x86Thunk.c
16
17 Abstract:
18
19 Real Mode Thunk Functions
20
21 --*/
22
23 #include "Thunk16Lib.h"
24 #include "EfiCommonLib.h"
25
26 #define IA32API __cdecl
27
28 extern CONST UINTN mCode16Size;
29
30 extern
31 IA32_REGISTER_SET *
32 IA32API
33 _Thunk16 (
34 IN OUT IA32_REGISTER_SET *RegisterSet,
35 IN UINT32 ThunkFlags,
36 IN UINT32 RealModeCs
37 );
38
39 extern
40 VOID
41 IA32API
42 _Code16Addr (
43 VOID
44 );
45
46 VOID
47 IA32API
48 AsmFxRestore (
49 IN CONST IA32_FX_BUFFER *Buffer
50 );
51
52 VOID
53 IA32API
54 AsmFxSave (
55 OUT IA32_FX_BUFFER *Buffer
56 );
57
58 //
59 // Implementation
60 //
61 STATIC
62 IA32_REGISTER_SET *
63 AsmThunk16 (
64 IN THUNK_CONTEXT *ThunkContext,
65 IN OUT IA32_REGISTER_SET *RegisterSet,
66 IN UINT32 ThunkFlags
67 )
68 /*++
69
70 Routine Description:
71
72 Do the 16-bit thunk code.
73
74 NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
75 disabled because of GDTR and IDTR manipulations.
76 This function must be placed in identity mapped pages.
77
78 Arguments:
79
80 ThunkContext - Thunk context to use.
81 RegisterSet - CPU registers would be set to the values contained in this
82 structure before making the far call. Then CPU registers are
83 copied back to this structure.
84 SS:ESP points to the real mode stack if THUNK_USER_STACK is
85 set on input, otherwise ignored.
86 EFlages is ignored on input.
87 On output, values of CS, EIP, SS and ESP should be ignored.
88 ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
89 THUNK_USER_STACK.
90 THUNK_SAVE_FP_STATE - FPU state would be saved/restored
91 before/after calling real mode code.
92 THUNK_USER_STACK - The stack specified by SS:ESP would be
93 used instead of the default stack.
94
95 Returns:
96
97 RegisterSet is returned.
98
99 --*/
100 {
101 IA32_FX_BUFFER *FpSavedState;
102 UINT8 FpBuffer[sizeof (*FpSavedState) + 0x10];
103
104 FpSavedState = (IA32_FX_BUFFER*)(((UINTN)FpBuffer + 0xf) & ~0xf);
105
106 if (!(ThunkFlags & THUNK_USER_STACK)) {
107 RegisterSet->E.ESP = (UINT16)ThunkContext->DefaultStack;
108 RegisterSet->E.SS = (UINT16)((ThunkContext->DefaultStack >> 4) & 0xf000);
109 }
110
111 if (ThunkFlags & THUNK_SAVE_FP_STATE) {
112 AsmFxSave (FpSavedState);
113 }
114
115 EfiCommonLibCopyMem (
116 RegisterSet,
117 _Thunk16 (
118 RegisterSet,
119 (UINT16)(ThunkFlags >> 16),
120 ThunkContext->RealModeBuffer >> 4
121 ),
122 sizeof (*RegisterSet)
123 );
124
125 if (ThunkFlags & THUNK_SAVE_FP_STATE) {
126 AsmFxRestore (FpSavedState);
127 }
128
129 return RegisterSet;
130 }
131
132 UINTN
133 EFIAPI
134 AsmThunk16GetProperties (
135 OUT UINTN *MinimumStackSize
136 )
137 /*++
138
139 Routine Description:
140
141 Returns the properties of this real mode thunk implementation. Currently
142 there are 2 properties has been defined, the minimum real mode buffer size
143 and the minimum stack size.
144
145 Arguments:
146
147 MinimumStackSize - The minimum size required for a 16-bit stack.
148
149 Returns:
150
151 The minimum size of the real mode buffer needed by this thunk implementation
152 is returned.
153
154 --*/
155 {
156 //
157 // This size should be large enough to hold the register set as well as saved
158 // CPU contexts including GDTR, CR0 and CR4
159 //
160 if (MinimumStackSize) {
161 *MinimumStackSize = sizeof (IA32_REGISTER_SET) + 0x200;
162 }
163
164 return mCode16Size;
165 }
166
167 THUNK_CONTEXT *
168 EFIAPI
169 AsmThunk16SetProperties (
170 OUT THUNK_CONTEXT *ThunkContext,
171 IN VOID *RealModeBuffer,
172 IN UINTN BufferSize
173 )
174 /*++
175
176 Routine Description:
177
178 Tell this real mode thunk implementation the address and size of the real
179 mode buffer needed.
180
181 Arguments:
182
183 ThunkContext - The thunk context whose properties to set.
184 RealModeBuffer - The address of the buffer allocated by caller. It should be
185 aligned on a 16-byte boundary.
186 This buffer must be in identity mapped pages.
187 BufferSize - The size of RealModeBuffer. Must be larger than the minimum
188 size required as returned by AsmThunk16GetProperties().
189
190 Returns:
191
192 None
193
194 --*/
195 {
196 BufferSize &= ~3;
197
198 ThunkContext->RealModeBuffer = (UINT32)(UINTN)RealModeBuffer;
199 ThunkContext->DefaultStack = (UINT32)(ThunkContext->RealModeBuffer + BufferSize);
200 EfiCommonLibCopyMem (RealModeBuffer, (VOID*)(UINTN)_Code16Addr, mCode16Size);
201
202 return ThunkContext;
203 }
204
205 VOID
206 EFIAPI
207 AsmThunk16Destroy (
208 IN OUT THUNK_CONTEXT *ThunkContext
209 )
210 /*++
211
212 Routine Description:
213
214 Reset all internal states to their initial values. The caller should not
215 release the real mode buffer until after a call to this function.
216
217 Arguments:
218
219 ThunkContext - The thunk context to destroy.
220
221 Returns:
222
223 None
224
225 --*/
226 {
227 ThunkContext->RealModeBuffer = 0;
228 }
229
230 IA32_REGISTER_SET *
231 EFIAPI
232 AsmThunk16FarCall86 (
233 IN THUNK_CONTEXT *ThunkContext,
234 IN OUT IA32_REGISTER_SET *RegisterSet,
235 IN UINT32 Flags
236 )
237 /*++
238
239 Routine Description:
240
241 Make a far call to 16-bit code.
242
243 NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
244 disabled because of GDTR and IDTR manipulations.
245 This function must be placed in identity mapped pages.
246
247 Arguments:
248
249 ThunkContext - Thunk context to use.
250 RegisterSet - CPU registers would be set to the values contained in this
251 structure before making the far call. Then CPU registers are
252 copied back to this structure.
253 CS:EIP points to the real mode code being called on input.
254 SS:ESP points to the real mode stack if THUNK_USER_STACK is
255 set on input, otherwise ignored.
256 EFlages is ignored on input.
257 On output, values of CS, EIP, SS and ESP should be ignored.
258 ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
259 THUNK_USER_STACK.
260 THUNK_SAVE_FP_STATE - FPU state would be saved/restored
261 before/after calling real mode code.
262 THUNK_USER_STACK - The stack specified by SS:ESP would be
263 used instead of the default stack.
264
265 Returns:
266
267 RegisterSet is returned.
268
269 --*/
270 {
271 return AsmThunk16 (ThunkContext, RegisterSet, Flags);
272 }
273
274 IA32_REGISTER_SET *
275 EFIAPI
276 AsmThunk16Int86 (
277 IN THUNK_CONTEXT *ThunkContext,
278 IN UINT8 IntNumber,
279 IN OUT IA32_REGISTER_SET *RegisterSet,
280 IN UINT32 Flags
281 )
282 /*++
283
284 Routine Description:
285
286 Invoke a 16-bit interrupt handler.
287
288 NOTE: This function must be called on TPL_HIGH_LEVEL or with interrupts
289 disabled because of GDTR and IDTR manipulations.
290 This function must be placed in identity mapped pages.
291
292 Arguments:
293
294 ThunkContext - Thunk context to use.
295 IntNumber - The ordinal of the interrupt handler ranging from 0 to 255.
296 RegisterSet - CPU registers would be set to the values contained in this
297 structure before making the far call. Then CPU registers are
298 copied back to this structure.
299 SS:ESP points to the real mode stack if THUNK_USER_STACK is
300 set on input, otherwise ignored.
301 EFlages is ignored on input.
302 On output, values of CS, EIP, SS and ESP should be ignored.
303 ThunkFlags - 2 flags have currently been defined, THUNK_SAVE_FP_STATE and
304 THUNK_USER_STACK.
305 THUNK_SAVE_FP_STATE - FPU state would be saved/restored
306 before/after calling real mode code.
307 THUNK_USER_STACK - The stack specified by SS:ESP would be
308 used instead of the default stack.
309
310 Returns:
311
312 RegisterSet is returned.
313
314 --*/
315 {
316 RegisterSet->E.EIP = (UINT16)((UINT32 *)NULL)[IntNumber];
317 RegisterSet->E.CS = (UINT16)(((UINT32 *)NULL)[IntNumber] >> 16);
318
319 return AsmThunk16 (ThunkContext, RegisterSet, Flags | THUNK_INTERRUPT);
320 }