remove some comments introduced by tools.
[mirror_edk2.git] / MdeModulePkg / Universal / DebugSupportDxe / Ia32 / plDebugSupport.c
1 /**@file
2 IA32 specific debug support functions
3
4 Copyright (c) 2006 - 2007, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 //
16 // private header files
17 //
18 #include "plDebugSupport.h"
19
20 //
21 // This the global main table to keep track of the interrupts
22 //
23 IDT_ENTRY *IdtEntryTable = NULL;
24 DESCRIPTOR NullDesc = 0;
25
26 STATIC
27 EFI_STATUS
28 CreateEntryStub (
29 IN EFI_EXCEPTION_TYPE ExceptionType,
30 OUT VOID **Stub
31 )
32 /*++
33
34 Routine Description: Allocate pool for a new IDT entry stub. Copy the generic
35 stub into the new buffer and fixup the vector number and jump target address.
36
37 Arguments:
38 ExceptionType - This is the exception type that the new stub will be created
39 for.
40 Stub - On successful exit, *Stub contains the newly allocated entry stub.
41 Returns:
42 Typically EFI_SUCCESS
43 other possibilities are passed through from AllocatePool
44
45 --*/
46 {
47 UINT8 *StubCopy;
48
49 StubCopy = *Stub;
50
51 //
52 // Fixup the stub code for this vector
53 //
54
55 // The stub code looks like this:
56 //
57 // 00000000 89 25 00000004 R mov AppEsp, esp ; save stack top
58 // 00000006 BC 00008014 R mov esp, offset DbgStkBot ; switch to debugger stack
59 // 0000000B 6A 00 push 0 ; push vector number - will be modified before installed
60 // 0000000D E9 db 0e9h ; jump rel32
61 // 0000000E 00000000 dd 0 ; fixed up to relative address of CommonIdtEntry
62 //
63
64 //
65 // poke in the exception type so the second push pushes the exception type
66 //
67 StubCopy[0x0c] = (UINT8) ExceptionType;
68
69 //
70 // fixup the jump target to point to the common entry
71 //
72 *(UINT32 *) &StubCopy[0x0e] = (UINT32) CommonIdtEntry - (UINT32) &StubCopy[StubSize];
73
74 return EFI_SUCCESS;
75 }
76
77 STATIC
78 EFI_STATUS
79 HookEntry (
80 IN EFI_EXCEPTION_TYPE ExceptionType,
81 IN VOID (*NewCallback) ()
82 )
83 /*++
84
85 Routine Description:
86 Creates a nes entry stub. Then saves the current IDT entry and replaces it
87 with an interrupt gate for the new entry point. The IdtEntryTable is updated
88 with the new registered function.
89
90 This code executes in boot services context. The stub entry executes in interrupt
91 context.
92
93 Arguments:
94 ExceptionType - specifies which vector to hook.
95 NewCallback - a pointer to the new function to be registered.
96
97 Returns:
98 EFI_SUCCESS
99 Other possibilities are passed through by CreateEntryStub
100
101 --*/
102 {
103 BOOLEAN OldIntFlagState;
104 EFI_STATUS Status;
105
106 Status = CreateEntryStub (ExceptionType, (VOID **) &IdtEntryTable[ExceptionType].StubEntry);
107 if (Status == EFI_SUCCESS) {
108 OldIntFlagState = WriteInterruptFlag (0);
109 ReadIdt (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));
110
111 ((UINT16 *) &IdtEntryTable[ExceptionType].OrigVector)[0] = ((UINT16 *) &IdtEntryTable[ExceptionType].OrigDesc)[0];
112 ((UINT16 *) &IdtEntryTable[ExceptionType].OrigVector)[1] = ((UINT16 *) &IdtEntryTable[ExceptionType].OrigDesc)[3];
113
114 Vect2Desc (&IdtEntryTable[ExceptionType].NewDesc, IdtEntryTable[ExceptionType].StubEntry);
115 IdtEntryTable[ExceptionType].RegisteredCallback = NewCallback;
116 WriteIdt (ExceptionType, &(IdtEntryTable[ExceptionType].NewDesc));
117 WriteInterruptFlag (OldIntFlagState);
118 }
119
120 return Status;
121 }
122
123 STATIC
124 EFI_STATUS
125 UnhookEntry (
126 IN EFI_EXCEPTION_TYPE ExceptionType
127 )
128 /*++
129
130 Routine Description:
131 Undoes HookEntry. This code executes in boot services context.
132
133 Arguments:
134 ExceptionType - specifies which entry to unhook
135
136 Returns:
137 EFI_SUCCESS
138
139 --*/
140 {
141 BOOLEAN OldIntFlagState;
142
143 OldIntFlagState = WriteInterruptFlag (0);
144 WriteIdt (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));
145 WriteInterruptFlag (OldIntFlagState);
146
147 return EFI_SUCCESS;
148 }
149
150 EFI_STATUS
151 ManageIdtEntryTable (
152 VOID (*NewCallback)(),
153 EFI_EXCEPTION_TYPE ExceptionType
154 )
155 /*++
156
157 Routine Description:
158 This is the main worker function that manages the state of the interrupt
159 handlers. It both installs and uninstalls interrupt handlers based on the
160 value of NewCallback. If NewCallback is NULL, then uninstall is indicated.
161 If NewCallback is non-NULL, then install is indicated.
162
163 Arguments:
164 NewCallback - If non-NULL, NewCallback specifies the new handler to register.
165 If NULL, specifies that the previously registered handler should
166 be uninstalled.
167 ExceptionType - Indicates which entry to manage
168
169 Returns:
170 EFI_SUCCESS
171 EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has
172 no handler registered for it
173 EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.
174
175 Other possible return values are passed through from UnHookEntry and HookEntry.
176
177 --*/
178 {
179 EFI_STATUS Status;
180
181 Status = EFI_SUCCESS;
182
183 if (FeaturePcdGet (PcdNtEmulatorEnable)) {
184 if (CompareDescriptor (&IdtEntryTable[ExceptionType].NewDesc, &NullDesc)) {
185 //
186 // we've already installed to this vector
187 //
188 if (NewCallback != NULL) {
189 //
190 // if the input handler is non-null, error
191 //
192 Status = EFI_ALREADY_STARTED;
193 } else {
194 Status = UnhookEntry (ExceptionType);
195 }
196 } else {
197 //
198 // no user handler installed on this vector
199 //
200 if (NewCallback == NULL) {
201 //
202 // if the input handler is null, error
203 //
204 Status = EFI_INVALID_PARAMETER;
205 } else {
206 Status = HookEntry (ExceptionType, NewCallback);
207 }
208 }
209 }
210
211 return Status;
212 }
213
214 EFI_STATUS
215 EFIAPI
216 GetMaximumProcessorIndex (
217 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
218 OUT UINTN *MaxProcessorIndex
219 )
220 /*++
221
222 Routine Description: This is a DebugSupport protocol member function.
223
224 Arguments:
225 This - The DebugSupport instance
226 MaxProcessorIndex - The maximuim supported processor index
227
228 Returns:
229 Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0
230
231 --*/
232 {
233 *MaxProcessorIndex = 0;
234 return (EFI_SUCCESS);
235 }
236
237 EFI_STATUS
238 EFIAPI
239 RegisterPeriodicCallback (
240 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
241 IN UINTN ProcessorIndex,
242 IN EFI_PERIODIC_CALLBACK PeriodicCallback
243 )
244 /*++
245
246 Routine Description: This is a DebugSupport protocol member function.
247
248 Arguments:
249 This - The DebugSupport instance
250 ProcessorIndex - Which processor the callback applies to.
251 PeriodicCallback - Callback function
252
253 Returns:
254
255 EFI_SUCCESS
256 EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has
257 no handler registered for it
258 EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.
259
260 Other possible return values are passed through from UnHookEntry and HookEntry.
261
262 --*/
263 {
264 return ManageIdtEntryTable (PeriodicCallback, SYSTEM_TIMER_VECTOR);
265 }
266
267 EFI_STATUS
268 EFIAPI
269 RegisterExceptionCallback (
270 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
271 IN UINTN ProcessorIndex,
272 IN EFI_EXCEPTION_CALLBACK NewCallback,
273 IN EFI_EXCEPTION_TYPE ExceptionType
274 )
275 /*++
276
277 Routine Description:
278 This is a DebugSupport protocol member function.
279
280 This code executes in boot services context.
281
282 Arguments:
283 This - The DebugSupport instance
284 ProcessorIndex - Which processor the callback applies to.
285 NewCallback - Callback function
286 ExceptionType - Which exception to hook
287
288 Returns:
289
290 EFI_SUCCESS
291 EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has
292 no handler registered for it
293 EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.
294
295 Other possible return values are passed through from UnHookEntry and HookEntry.
296
297 --*/
298 {
299 return ManageIdtEntryTable (NewCallback, ExceptionType);
300 }
301
302 EFI_STATUS
303 EFIAPI
304 InvalidateInstructionCache (
305 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
306 IN UINTN ProcessorIndex,
307 IN VOID *Start,
308 IN UINT64 Length
309 )
310 /*++
311
312 Routine Description:
313 This is a DebugSupport protocol member function.
314 Calls assembly routine to flush cache.
315
316 Arguments:
317 This - The DebugSupport instance
318 ProcessorIndex - Which processor the callback applies to.
319 Start - Physical base of the memory range to be invalidated
320 Length - mininum number of bytes in instruction cache to invalidate
321
322 Returns:
323
324 EFI_SUCCESS - always return success
325
326 --*/
327 {
328 AsmWbinvd ();
329 return EFI_SUCCESS;
330 }
331
332 EFI_STATUS
333 plInitializeDebugSupportDriver (
334 VOID
335 )
336 /*++
337
338 Routine Description:
339 Initializes driver's handler registration database.
340
341 This code executes in boot services context.
342
343 Arguments:
344 None
345
346 Returns:
347 EFI_SUCCESS
348 EFI_UNSUPPORTED - if IA32 processor does not support FXSTOR/FXRSTOR instructions,
349 the context save will fail, so these processor's are not supported.
350 EFI_OUT_OF_RESOURCES - not resource to finish initialization
351
352 --*/
353 {
354 EFI_EXCEPTION_TYPE ExceptionType;
355
356 if (!FxStorSupport ()) {
357 return EFI_UNSUPPORTED;
358 }
359
360 IdtEntryTable = AllocateZeroPool (sizeof (IDT_ENTRY) * NUM_IDT_ENTRIES);
361 if (IdtEntryTable == NULL) {
362 return EFI_OUT_OF_RESOURCES;
363 }
364
365 for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {
366 IdtEntryTable[ExceptionType].StubEntry = (DEBUG_PROC) (UINTN) AllocatePool (StubSize);
367 if (IdtEntryTable[ExceptionType].StubEntry == NULL) {
368 goto ErrorCleanup;
369 }
370
371 CopyMem ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry, InterruptEntryStub, StubSize);
372 }
373 return EFI_SUCCESS;
374
375 ErrorCleanup:
376
377 for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {
378 if (IdtEntryTable[ExceptionType].StubEntry != NULL) {
379 FreePool ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry);
380 }
381 }
382 FreePool (IdtEntryTable);
383
384 return EFI_OUT_OF_RESOURCES;
385 }
386
387 EFI_STATUS
388 EFIAPI
389 plUnloadDebugSupportDriver (
390 IN EFI_HANDLE ImageHandle
391 )
392 /*++
393
394 Routine Description:
395 This is the callback that is written to the LoadedImage protocol instance
396 on the image handle. It uninstalls all registered handlers and frees all entry
397 stub memory.
398
399 This code executes in boot services context.
400
401 Arguments:
402 ImageHandle - The image handle of the unload handler
403
404 Returns:
405
406 EFI_SUCCESS - always return success
407
408 --*/
409 {
410 EFI_EXCEPTION_TYPE ExceptionType;
411
412 for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {
413 ManageIdtEntryTable (NULL, ExceptionType);
414 }
415
416 FreePool (IdtEntryTable);
417 return EFI_SUCCESS;
418 }
419
420 VOID
421 InterruptDistrubutionHub (
422 EFI_EXCEPTION_TYPE ExceptionType,
423 EFI_SYSTEM_CONTEXT_IA32 *ContextRecord
424 )
425 /*++
426
427 Routine Description: Common piece of code that invokes the registered handlers.
428
429 This code executes in exception context so no efi calls are allowed.
430
431 Arguments:
432 ExceptionType - exception type
433 ContextRecord - system context
434
435 Returns:
436
437 None
438
439 --*/
440 {
441 if (IdtEntryTable[ExceptionType].RegisteredCallback != NULL) {
442 if (ExceptionType != SYSTEM_TIMER_VECTOR) {
443 IdtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, ContextRecord);
444 } else {
445 OrigVector = IdtEntryTable[ExceptionType].OrigVector;
446 IdtEntryTable[ExceptionType].RegisteredCallback (ContextRecord);
447 }
448 }
449 }