]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DebugSupportDxe/Ipf/PlDebugSupport.c
filename renaming to meet coding style.
[mirror_edk2.git] / MdeModulePkg / Universal / DebugSupportDxe / Ipf / PlDebugSupport.c
CommitLineData
c1f23d63 1/**@file\r
2 IPF specific debug support functions\r
3\r
19b15d63 4Copyright (c) 2006 - 2008, Intel Corporation \r
c1f23d63 5All rights reserved. This program and the accompanying materials \r
6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php \r
9 \r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13**/\r
14\r
15//\r
16// private header files\r
17//\r
e9f9d09a 18#include "PlDebugSupport.h"\r
c1f23d63 19\r
19b15d63 20BOOLEAN mInHandler = FALSE;\r
21\r
c1f23d63 22typedef struct {\r
23 UINT64 low;\r
24 UINT64 high;\r
25} BUNDLE;\r
26\r
27//\r
28// number of bundles to swap in ivt\r
29//\r
30#define NUM_BUNDLES_IN_STUB 5\r
31#define NUM_IVT_ENTRIES 64\r
32\r
33typedef struct {\r
34 BUNDLE OrigBundles[NUM_BUNDLES_IN_STUB];\r
35 VOID (*RegisteredCallback) ();\r
36} IVT_ENTRY;\r
37\r
c1f23d63 38EFI_STATUS\r
39ManageIvtEntryTable (\r
40 IN EFI_EXCEPTION_TYPE ExceptionType,\r
41 IN BUNDLE NewBundles[4],\r
42 IN VOID (*NewCallback) ()\r
43 );\r
44\r
c1f23d63 45VOID\r
46HookEntry (\r
47 IN EFI_EXCEPTION_TYPE ExceptionType,\r
48 IN BUNDLE NewBundles[4],\r
49 IN VOID (*NewCallback) ()\r
50 );\r
51\r
c1f23d63 52VOID\r
53UnhookEntry (\r
54 IN EFI_EXCEPTION_TYPE ExceptionType\r
55 );\r
56\r
c1f23d63 57VOID\r
58ChainExternalInterrupt (\r
59 IN VOID (*NewCallback) ()\r
60 );\r
61\r
c1f23d63 62VOID\r
63UnchainExternalInterrupt (\r
64 VOID\r
65 );\r
66\r
c1f23d63 67VOID\r
68GetHandlerEntryPoint (\r
69 UINTN HandlerIndex,\r
70 VOID **EntryPoint\r
71 );\r
72\r
73IVT_ENTRY IvtEntryTable[NUM_IVT_ENTRIES];\r
74\r
75//\r
76// IPF context record is overallocated by 512 bytes to guarantee a 512 byte alignment exists\r
77// within the buffer and still have a large enough buffer to hold a whole IPF context record.\r
78//\r
79UINT8 IpfContextBuf[sizeof (EFI_SYSTEM_CONTEXT_IPF) + 512];\r
80\r
81//\r
82// The PatchSaveBuffer is used to store the original bundles from the IVT where it is patched\r
83// with the common handler.\r
84//\r
85UINT8 PatchSaveBuffer[0x400];\r
86UINTN ExternalInterruptCount;\r
87\r
88EFI_STATUS\r
89plInitializeDebugSupportDriver (\r
90 VOID\r
91 )\r
92/*++\r
93\r
94Routine Description:\r
95 IPF specific DebugSupport driver initialization. Must be public because it's\r
96 referenced from DebugSupport.c\r
97\r
98Arguments:\r
99\r
100Returns:\r
101\r
102 EFI_SUCCESS\r
103\r
104--*/\r
105{\r
106 SetMem (IvtEntryTable, sizeof (IvtEntryTable), 0);\r
107 ExternalInterruptCount = 0;\r
108 return EFI_SUCCESS;\r
109}\r
110\r
111EFI_STATUS\r
112EFIAPI\r
113plUnloadDebugSupportDriver (\r
114 IN EFI_HANDLE ImageHandle\r
115 )\r
116/*++\r
117\r
118Routine Description:\r
119 Unload handler that is called during UnloadImage() - deallocates pool memory\r
120 used by the driver. Must be public because it's referenced from DebugSuport.c\r
121\r
122Arguments:\r
123 ImageHandle - Image handle\r
124\r
125Returns:\r
126\r
127 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.\r
128\r
129--*/\r
130{\r
131 EFI_EXCEPTION_TYPE ExceptionType;\r
132\r
133 for (ExceptionType = 0; ExceptionType < NUM_IVT_ENTRIES; ExceptionType++) {\r
134 ManageIvtEntryTable (ExceptionType, NULL, NULL);\r
135 }\r
136\r
137 return EFI_SUCCESS;\r
138}\r
139\r
140VOID\r
141CommonHandler (\r
142 IN EFI_EXCEPTION_TYPE ExceptionType,\r
143 IN EFI_SYSTEM_CONTEXT Context\r
144 )\r
145/*++\r
146\r
147Routine Description:\r
148 C routine that is called for all registered exceptions. This is the main\r
149 exception dispatcher. Must be public because it's referenced from AsmFuncs.s.\r
150\r
151Arguments:\r
152 ExceptionType - Exception Type\r
153 Context - System Context\r
154\r
155Returns:\r
156\r
157 Nothing\r
158 \r
159--*/\r
160{\r
c1f23d63 161 DEBUG_CODE_BEGIN ();\r
19b15d63 162 if (mInHandler) {\r
c1f23d63 163 DEBUG ((EFI_D_INFO, "ERROR: Re-entered debugger!\n"\r
164 " ExceptionType == %X\n"\r
165 " Context == %X\n"\r
166 " Context.SystemContextIpf->CrIip == %X\n"\r
167 " Context.SystemContextIpf->CrIpsr == %X\n"\r
19b15d63 168 " mInHandler == %X\n",\r
c1f23d63 169 ExceptionType, \r
170 Context, \r
171 Context.SystemContextIpf->CrIip,\r
172 Context.SystemContextIpf->CrIpsr,\r
19b15d63 173 mInHandler));\r
c1f23d63 174 }\r
175 DEBUG_CODE_END ();\r
176\r
19b15d63 177 ASSERT (!mInHandler);\r
178 mInHandler = TRUE;\r
c1f23d63 179 if (IvtEntryTable[ExceptionType].RegisteredCallback != NULL) {\r
180 if (ExceptionType != EXCEPT_IPF_EXTERNAL_INTERRUPT) {\r
181 IvtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, Context.SystemContextIpf);\r
182 } else {\r
183 IvtEntryTable[ExceptionType].RegisteredCallback (Context.SystemContextIpf);\r
184 }\r
185 } else {\r
186 ASSERT (0);\r
187 }\r
188\r
19b15d63 189 mInHandler = FALSE;\r
c1f23d63 190}\r
191\r
c1f23d63 192VOID\r
193GetHandlerEntryPoint (\r
194 UINTN HandlerIndex,\r
195 VOID **EntryPoint\r
196 )\r
197/*++\r
198\r
199Routine Description:\r
200 Given an integer number, return the physical address of the entry point in the IFT\r
201 \r
202Arguments:\r
203 HandlerIndex - Index of the Handler \r
204 EntryPoint - IFT Entrypoint\r
205\r
206Returns:\r
207\r
208 Nothing\r
209 \r
210--*/\r
211{\r
212 UINT8 *TempPtr;\r
213\r
214 //\r
215 // get base address of IVT\r
216 //\r
217 TempPtr = GetIva ();\r
218\r
219 if (HandlerIndex < 20) {\r
220 //\r
221 // first 20 provide 64 bundles per vector\r
222 //\r
223 TempPtr += 0x400 * HandlerIndex;\r
224 } else {\r
225 //\r
226 // the rest provide 16 bundles per vector\r
227 //\r
228 TempPtr += 0x5000 + 0x100 * (HandlerIndex - 20);\r
229 }\r
230\r
231 *EntryPoint = (VOID *) TempPtr;\r
232}\r
233\r
c1f23d63 234EFI_STATUS\r
235ManageIvtEntryTable (\r
236 IN EFI_EXCEPTION_TYPE ExceptionType,\r
237 IN BUNDLE NewBundles[NUM_BUNDLES_IN_STUB],\r
238 IN VOID (*NewCallback) ()\r
239 )\r
240/*++\r
241\r
242Routine Description:\r
243 This is the worker function that installs and removes all handlers\r
244 \r
245Arguments:\r
246 ExceptionType - Exception Type\r
247 NewBundles - New Boundles\r
248 NewCallback - New Callback\r
249\r
250Returns:\r
251\r
252 EFI_STATUS - any return other than EFI_SUCCESS indicates the request was not\r
253 satisfied.\r
254 EFI_ALEADY_STARTED - Ivt already hooked.\r
255 \r
256--*/\r
257{\r
258 BUNDLE *B0Ptr;\r
259 UINT64 InterruptFlags;\r
260 EFI_TPL OldTpl;\r
261\r
262 //\r
263 // Get address of bundle 0\r
264 //\r
265 GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr);\r
266\r
267 if (IvtEntryTable[ExceptionType].RegisteredCallback != NULL) {\r
268 //\r
269 // we've already installed to this vector\r
270 //\r
271 if (NewCallback != NULL) {\r
272 //\r
273 // if the input handler is non-null, error\r
274 //\r
275 return EFI_ALREADY_STARTED;\r
276 } else {\r
277 //\r
278 // else remove the previously installed handler\r
279 //\r
280 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
281 InterruptFlags = ProgramInterruptFlags (DISABLE_INTERRUPTS);\r
282 if (ExceptionType == EXCEPT_IPF_EXTERNAL_INTERRUPT) {\r
283 UnchainExternalInterrupt ();\r
284 } else {\r
285 UnhookEntry (ExceptionType);\r
286 }\r
287\r
288 ProgramInterruptFlags (InterruptFlags);\r
289 gBS->RestoreTPL (OldTpl);\r
290 //\r
291 // re-init IvtEntryTable\r
292 //\r
293 SetMem (&IvtEntryTable[ExceptionType], sizeof (IVT_ENTRY), 0);\r
294 }\r
295 } else {\r
296 //\r
297 // no user handler installed on this vector\r
298 //\r
299 if (NewCallback != NULL) {\r
300 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
301 InterruptFlags = ProgramInterruptFlags (DISABLE_INTERRUPTS);\r
302 if (ExceptionType == EXCEPT_IPF_EXTERNAL_INTERRUPT) {\r
303 ChainExternalInterrupt (NewCallback);\r
304 } else {\r
305 HookEntry (ExceptionType, NewBundles, NewCallback);\r
306 }\r
307\r
308 ProgramInterruptFlags (InterruptFlags);\r
309 gBS->RestoreTPL (OldTpl);\r
310 }\r
311 }\r
312\r
313 return EFI_SUCCESS;\r
314}\r
315\r
c1f23d63 316VOID\r
317HookEntry (\r
318 IN EFI_EXCEPTION_TYPE ExceptionType,\r
319 IN BUNDLE NewBundles[4],\r
320 IN VOID (*NewCallback) ()\r
321 )\r
322/*++\r
323\r
324Routine Description:\r
325 Saves original IVT contents and inserts a few new bundles which are fixed up\r
326 to store the ExceptionType and then call the common handler.\r
327 \r
328Arguments:\r
329 ExceptionType - Exception Type\r
330 NewBundles - New Boundles\r
331 NewCallback - New Callback\r
332\r
333Returns:\r
334\r
335 Nothing\r
336 \r
337--*/\r
338{\r
339 BUNDLE *FixupBundle;\r
340 BUNDLE *B0Ptr;\r
341\r
342 //\r
343 // Get address of bundle 0\r
344 //\r
345 GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr);\r
346\r
347 //\r
348 // copy original bundles from IVT to IvtEntryTable so we can restore them later\r
349 //\r
350 CopyMem (\r
351 IvtEntryTable[ExceptionType].OrigBundles,\r
352 B0Ptr,\r
353 sizeof (BUNDLE) * NUM_BUNDLES_IN_STUB\r
354 );\r
355 //\r
356 // insert new B0\r
357 //\r
358 CopyMem (B0Ptr, NewBundles, sizeof (BUNDLE) * NUM_BUNDLES_IN_STUB);\r
359\r
360 //\r
361 // fixup IVT entry so it stores its index and whether or not to chain...\r
362 //\r
363 FixupBundle = B0Ptr + 2;\r
364 FixupBundle->high |= ExceptionType << 36;\r
365\r
366 InstructionCacheFlush (B0Ptr, 5);\r
367 IvtEntryTable[ExceptionType].RegisteredCallback = NewCallback;\r
368}\r
369\r
c1f23d63 370VOID\r
371UnhookEntry (\r
372 IN EFI_EXCEPTION_TYPE ExceptionType\r
373 )\r
374/*++\r
375\r
376Routine Description:\r
377 Restores original IVT contents when unregistering a callback function\r
378 \r
379Arguments:\r
380 ExceptionType - Exception Type\r
381 NewBundles - New Boundles\r
382 NewCallback - New Callback\r
383\r
384Returns:\r
385\r
386 Nothing\r
387 \r
388--*/\r
389{\r
390 BUNDLE *B0Ptr;\r
391\r
392 //\r
393 // Get address of bundle 0\r
394 //\r
395 GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr);\r
396 //\r
397 // restore original bundles in IVT\r
398 //\r
399 CopyMem (\r
400 B0Ptr,\r
401 IvtEntryTable[ExceptionType].OrigBundles,\r
402 sizeof (BUNDLE) * NUM_BUNDLES_IN_STUB\r
403 );\r
404 InstructionCacheFlush (B0Ptr, 5);\r
405}\r
406\r
c1f23d63 407VOID\r
408ChainExternalInterrupt (\r
409 IN VOID (*NewCallback) ()\r
410 )\r
411/*++\r
412\r
413Routine Description:\r
414 Sets up cache flush and calls assembly function to chain external interrupt.\r
415 Records new callback in IvtEntryTable.\r
416 \r
417Arguments:\r
418 NewCallback - New Callback\r
419\r
420Returns:\r
421\r
422 Nothing\r
423 \r
424--*/\r
425{\r
426 VOID *Start;\r
427\r
428 Start = (VOID *) ((UINT8 *) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT + 0x400);\r
429 IvtEntryTable[EXCEPT_IPF_EXTERNAL_INTERRUPT].RegisteredCallback = NewCallback;\r
430 ChainHandler ();\r
431 InstructionCacheFlush (Start, 0x400);\r
432}\r
433\r
c1f23d63 434VOID\r
435UnchainExternalInterrupt (\r
436 VOID\r
437 )\r
438/*++\r
439\r
440Routine Description:\r
441 Sets up cache flush and calls assembly function to restore external interrupt.\r
442 Removes registered callback from IvtEntryTable.\r
443 \r
444Arguments:\r
445 Nothing\r
446 \r
447Returns:\r
448\r
449 Nothing\r
450 \r
451--*/\r
452{\r
453 VOID *Start;\r
454\r
455 Start = (VOID *) ((UINT8 *) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT + 0x400);\r
456 UnchainHandler ();\r
457 InstructionCacheFlush (Start, 0x400);\r
458 IvtEntryTable[EXCEPT_IPF_EXTERNAL_INTERRUPT].RegisteredCallback = NULL;\r
459}\r
460\r
461//\r
462// The rest of the functions in this file are all member functions for the\r
463// DebugSupport protocol\r
464//\r
465\r
466EFI_STATUS\r
467EFIAPI\r
468GetMaximumProcessorIndex (\r
469 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
470 OUT UINTN *MaxProcessorIndex\r
471 )\r
472/*++\r
473\r
474Routine Description: This is a DebugSupport protocol member function. Hard\r
475 coded to support only 1 processor for now.\r
476\r
477Arguments:\r
478 This - The DebugSupport instance\r
479 MaxProcessorIndex - The maximuim supported processor index\r
480\r
481Returns:\r
482 Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0\r
483\r
484--*/\r
485{\r
486 *MaxProcessorIndex = 0;\r
487 return (EFI_SUCCESS);\r
488}\r
489\r
490EFI_STATUS\r
491EFIAPI\r
492RegisterPeriodicCallback (\r
493 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
494 IN UINTN ProcessorIndex,\r
495 IN EFI_PERIODIC_CALLBACK NewPeriodicCallback\r
496 )\r
497/*++\r
498\r
499Routine Description:\r
500 DebugSupport protocol member function\r
501\r
502Arguments:\r
503 This - The DebugSupport instance\r
504 ProcessorIndex - Which processor the callback applies to.\r
505 PeriodicCallback - Callback function\r
506\r
507Returns:\r
508\r
509 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.\r
510\r
511--*/\r
512{\r
513 return ManageIvtEntryTable (EXCEPT_IPF_EXTERNAL_INTERRUPT, NULL, NewPeriodicCallback);\r
514}\r
515\r
516EFI_STATUS\r
517EFIAPI\r
518RegisterExceptionCallback (\r
519 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
520 IN UINTN ProcessorIndex,\r
521 IN EFI_EXCEPTION_CALLBACK NewCallback,\r
522 IN EFI_EXCEPTION_TYPE ExceptionType\r
523 )\r
524/*++\r
525\r
526Routine Description:\r
527 DebugSupport protocol member function\r
528\r
529Arguments:\r
530 This - The DebugSupport instance\r
531 ProcessorIndex - Which processor the callback applies to.\r
532 NewCallback - Callback function\r
533 ExceptionType - Which exception to hook\r
534\r
535Returns:\r
536\r
537 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.\r
538\r
539--*/\r
540{\r
541 return ManageIvtEntryTable (\r
542 ExceptionType,\r
543 (BUNDLE *) ((EFI_PLABEL *) HookStub)->EntryPoint,\r
544 NewCallback\r
545 );\r
546}\r
547\r
548EFI_STATUS\r
549EFIAPI\r
550InvalidateInstructionCache (\r
551 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
552 IN UINTN ProcessorIndex,\r
553 IN VOID *Start,\r
554 IN UINTN Length\r
555 )\r
556/*++\r
557\r
558Routine Description:\r
559 DebugSupport protocol member function. Calls assembly routine to flush cache.\r
560\r
561Arguments:\r
562 This - The DebugSupport instance\r
563 ProcessorIndex - Which processor the callback applies to.\r
564 Start - Physical base of the memory range to be invalidated\r
565 Length - mininum number of bytes in instruction cache to invalidate\r
566\r
567Returns:\r
568 EFI_SUCCESS\r
569\r
570--*/\r
571{\r
572 InstructionCacheFlush (Start, Length);\r
573 return (EFI_SUCCESS);\r
574}\r