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