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