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