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