3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. 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
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.
18 IPF specific debug support functions
25 // Master EFI header file
30 // Common library header files
32 #include "EfiDriverLib.h"
37 #include EFI_PROTOCOL_DEFINITION (DebugSupport)
40 // private header files
42 #include "plDebugSupport.h"
50 // number of bundles to swap in ivt
52 #define NUM_BUNDLES_IN_STUB 5
53 #define NUM_IVT_ENTRIES 64
56 BUNDLE OrigBundles
[NUM_BUNDLES_IN_STUB
];
57 VOID (*RegisteredCallback
) ();
63 IN EFI_EXCEPTION_TYPE ExceptionType
,
64 IN BUNDLE NewBundles
[4],
65 IN
VOID (*NewCallback
) ()
71 IN EFI_EXCEPTION_TYPE ExceptionType
,
72 IN BUNDLE NewBundles
[4],
73 IN
VOID (*NewCallback
) ()
79 IN EFI_EXCEPTION_TYPE ExceptionType
84 ChainExternalInterrupt (
85 IN
VOID (*NewCallback
) ()
90 UnchainExternalInterrupt (
96 GetHandlerEntryPoint (
101 IVT_ENTRY IvtEntryTable
[NUM_IVT_ENTRIES
];
104 // IPF context record is overallocated by 512 bytes to guarantee a 512 byte alignment exists
105 // within the buffer and still have a large enough buffer to hold a whole IPF context record.
107 UINT8 IpfContextBuf
[sizeof (EFI_SYSTEM_CONTEXT_IPF
) + 512];
110 // The PatchSaveBuffer is used to store the original bundles from the IVT where it is patched
111 // with the common handler.
113 UINT8 PatchSaveBuffer
[0x400];
114 UINTN ExternalInterruptCount
;
117 plInitializeDebugSupportDriver (
123 IPF specific DebugSupport driver initialization. Must be public because it's
124 referenced from DebugSupport.c
134 gBS
->SetMem (IvtEntryTable
, sizeof (IvtEntryTable
), 0);
135 ExternalInterruptCount
= 0;
141 plUnloadDebugSupportDriver (
142 IN EFI_HANDLE ImageHandle
147 Unload handler that is called during UnloadImage() - deallocates pool memory
148 used by the driver. Must be public because it's referenced from DebugSuport.c
151 IN EFI_HANDLE ImageHandle
155 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.
158 // TODO: ImageHandle - add argument and description to function comment
160 EFI_EXCEPTION_TYPE ExceptionType
;
162 for (ExceptionType
= 0; ExceptionType
< NUM_IVT_ENTRIES
; ExceptionType
++) {
163 ManageIvtEntryTable (ExceptionType
, NULL
, NULL
);
171 IN EFI_EXCEPTION_TYPE ExceptionType
,
172 IN EFI_SYSTEM_CONTEXT Context
177 C routine that is called for all registered exceptions. This is the main
178 exception dispatcher. Must be public because it's referenced from AsmFuncs.s.
181 IN EFI_EXCEPTION_TYPE ExceptionType,
182 IN EFI_SYSTEM_CONTEXT Context
189 // TODO: ExceptionType - add argument and description to function comment
190 // TODO: Context - add argument and description to function comment
192 static BOOLEAN InHandler
= FALSE
;
196 EfiDebugPrint (EFI_D_GENERIC
, "ERROR: Re-entered debugger!\n"
197 " ExceptionType == %X\n"
199 " Context.SystemContextIpf->CrIip == %X\n"
200 " Context.SystemContextIpf->CrIpsr == %X\n"
201 " InHandler == %X\n",
204 Context
.SystemContextIpf
->CrIip
,
205 Context
.SystemContextIpf
->CrIpsr
,
212 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
213 if (ExceptionType
!= EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
214 IvtEntryTable
[ExceptionType
].RegisteredCallback (ExceptionType
, Context
.SystemContextIpf
);
216 IvtEntryTable
[ExceptionType
].RegisteredCallback (Context
.SystemContextIpf
);
227 GetHandlerEntryPoint (
234 Given an integer number, return the physical address of the entry point in the IFT
245 // TODO: HandlerIndex - add argument and description to function comment
246 // TODO: EntryPoint - add argument and description to function comment
251 // get base address of IVT
255 if (HandlerIndex
< 20) {
257 // first 20 provide 64 bundles per vector
259 TempPtr
+= 0x400 * HandlerIndex
;
262 // the rest provide 16 bundles per vector
264 TempPtr
+= 0x5000 + 0x100 * (HandlerIndex
- 20);
267 *EntryPoint
= (VOID
*) TempPtr
;
272 ManageIvtEntryTable (
273 IN EFI_EXCEPTION_TYPE ExceptionType
,
274 IN BUNDLE NewBundles
[NUM_BUNDLES_IN_STUB
],
275 IN
VOID (*NewCallback
) ()
280 This is the worker function that installs and removes all handlers
283 IN EFI_EXCEPTION_TYPE ExceptionType,
284 IN BUNDLE NewBundles[NUM_BUNDLES_IN_STUB],
285 IN VOID (*NewCallback) ()
289 EFI_STATUS - any return other than EFI_SUCCESS indicates the request was not
293 // TODO: ExceptionType - add argument and description to function comment
294 // TODO: ] - add argument and description to function comment
295 // TODO: ) - add argument and description to function comment
296 // TODO: EFI_ALREADY_STARTED - add return value to function comment
299 UINT64 InterruptFlags
;
303 // Get address of bundle 0
305 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
307 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
309 // we've already installed to this vector
311 if (NewCallback
!= NULL
) {
313 // if the input handler is non-null, error
315 return EFI_ALREADY_STARTED
;
318 // else remove the previously installed handler
320 OldTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
321 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
322 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
323 UnchainExternalInterrupt ();
325 UnhookEntry (ExceptionType
);
328 ProgramInterruptFlags (InterruptFlags
);
329 gBS
->RestoreTPL (OldTpl
);
331 // re-init IvtEntryTable
333 gBS
->SetMem (&IvtEntryTable
[ExceptionType
], sizeof (IVT_ENTRY
), 0);
337 // no user handler installed on this vector
339 if (NewCallback
!= NULL
) {
340 OldTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
341 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
342 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
343 ChainExternalInterrupt (NewCallback
);
345 HookEntry (ExceptionType
, NewBundles
, NewCallback
);
348 ProgramInterruptFlags (InterruptFlags
);
349 gBS
->RestoreTPL (OldTpl
);
359 IN EFI_EXCEPTION_TYPE ExceptionType
,
360 IN BUNDLE NewBundles
[4],
361 IN
VOID (*NewCallback
) ()
366 Saves original IVT contents and inserts a few new bundles which are fixed up
367 to store the ExceptionType and then call the common handler.
370 IN EFI_EXCEPTION_TYPE ExceptionType,
371 IN BUNDLE NewBundles[4],
372 IN VOID (*NewCallback) ()
379 // TODO: ExceptionType - add argument and description to function comment
380 // TODO: ] - add argument and description to function comment
381 // TODO: ) - add argument and description to function comment
387 // Get address of bundle 0
389 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
392 // copy original bundles from IVT to IvtEntryTable so we can restore them later
395 IvtEntryTable
[ExceptionType
].OrigBundles
,
397 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
402 gBS
->CopyMem (B0Ptr
, NewBundles
, sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
);
405 // fixup IVT entry so it stores its index and whether or not to chain...
407 FixupBundle
= B0Ptr
+ 2;
408 FixupBundle
->high
|= ExceptionType
<< 36;
410 InstructionCacheFlush (B0Ptr
, 5);
411 IvtEntryTable
[ExceptionType
].RegisteredCallback
= NewCallback
;
417 IN EFI_EXCEPTION_TYPE ExceptionType
422 Restores original IVT contents when unregistering a callback function
425 IN EFI_EXCEPTION_TYPE ExceptionType,
432 // TODO: ExceptionType - add argument and description to function comment
437 // Get address of bundle 0
439 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
441 // restore original bundles in IVT
445 IvtEntryTable
[ExceptionType
].OrigBundles
,
446 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
448 InstructionCacheFlush (B0Ptr
, 5);
453 ChainExternalInterrupt (
454 IN
VOID (*NewCallback
) ()
459 Sets up cache flush and calls assembly function to chain external interrupt.
460 Records new callback in IvtEntryTable.
463 IN VOID (*NewCallback) ()
470 // TODO: ) - add argument and description to function comment
474 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
475 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NewCallback
;
477 InstructionCacheFlush (Start
, 0x400);
482 UnchainExternalInterrupt (
488 Sets up cache flush and calls assembly function to restore external interrupt.
489 Removes registered callback from IvtEntryTable.
502 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
504 InstructionCacheFlush (Start
, 0x400);
505 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NULL
;
509 // The rest of the functions in this file are all member functions for the
510 // DebugSupport protocol
515 GetMaximumProcessorIndex (
516 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
517 OUT UINTN
*MaxProcessorIndex
521 Routine Description: This is a DebugSupport protocol member function. Hard
522 coded to support only 1 processor for now.
526 Returns: Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0
529 // TODO: This - add argument and description to function comment
530 // TODO: MaxProcessorIndex - add argument and description to function comment
532 *MaxProcessorIndex
= 0;
533 return (EFI_SUCCESS
);
538 RegisterPeriodicCallback (
539 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
540 IN UINTN ProcessorIndex
,
541 IN EFI_PERIODIC_CALLBACK NewPeriodicCallback
546 DebugSupport protocol member function
549 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
550 IN UINTN ProcessorIndex,
551 IN EFI_PERIODIC_CALLBACK NewPeriodicCallback
555 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.
558 // TODO: This - add argument and description to function comment
559 // TODO: ProcessorIndex - add argument and description to function comment
560 // TODO: NewPeriodicCallback - add argument and description to function comment
562 return ManageIvtEntryTable (EXCEPT_IPF_EXTERNAL_INTERRUPT
, NULL
, NewPeriodicCallback
);
567 RegisterExceptionCallback (
568 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
569 IN UINTN ProcessorIndex
,
570 IN EFI_EXCEPTION_CALLBACK NewCallback
,
571 IN EFI_EXCEPTION_TYPE ExceptionType
576 DebugSupport protocol member function
579 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
580 IN EFI_EXCEPTION_CALLBACK NewCallback,
581 IN EFI_EXCEPTION_TYPE ExceptionType
585 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.
588 // TODO: This - add argument and description to function comment
589 // TODO: ProcessorIndex - add argument and description to function comment
590 // TODO: NewCallback - add argument and description to function comment
591 // TODO: ExceptionType - add argument and description to function comment
593 return ManageIvtEntryTable (
595 (BUNDLE
*) ((EFI_PLABEL
*) HookStub
)->EntryPoint
,
602 InvalidateInstructionCache (
603 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
604 IN UINTN ProcessorIndex
,
611 DebugSupport protocol member function. Calls assembly routine to flush cache.
619 // TODO: This - add argument and description to function comment
620 // TODO: ProcessorIndex - add argument and description to function comment
621 // TODO: Start - add argument and description to function comment
622 // TODO: Length - add argument and description to function comment
624 InstructionCacheFlush (Start
, Length
);
625 return (EFI_SUCCESS
);