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
,
211 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
212 if (ExceptionType
!= EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
213 IvtEntryTable
[ExceptionType
].RegisteredCallback (ExceptionType
, Context
.SystemContextIpf
);
215 IvtEntryTable
[ExceptionType
].RegisteredCallback (Context
.SystemContextIpf
);
226 GetHandlerEntryPoint (
233 Given an integer number, return the physical address of the entry point in the IFT
244 // TODO: HandlerIndex - add argument and description to function comment
245 // TODO: EntryPoint - add argument and description to function comment
250 // get base address of IVT
254 if (HandlerIndex
< 20) {
256 // first 20 provide 64 bundles per vector
258 TempPtr
+= 0x400 * HandlerIndex
;
261 // the rest provide 16 bundles per vector
263 TempPtr
+= 0x5000 + 0x100 * (HandlerIndex
- 20);
266 *EntryPoint
= (VOID
*) TempPtr
;
271 ManageIvtEntryTable (
272 IN EFI_EXCEPTION_TYPE ExceptionType
,
273 IN BUNDLE NewBundles
[NUM_BUNDLES_IN_STUB
],
274 IN
VOID (*NewCallback
) ()
279 This is the worker function that installs and removes all handlers
282 IN EFI_EXCEPTION_TYPE ExceptionType,
283 IN BUNDLE NewBundles[NUM_BUNDLES_IN_STUB],
284 IN VOID (*NewCallback) ()
288 EFI_STATUS - any return other than EFI_SUCCESS indicates the request was not
292 // TODO: ExceptionType - add argument and description to function comment
293 // TODO: ] - add argument and description to function comment
294 // TODO: ) - add argument and description to function comment
295 // TODO: EFI_ALREADY_STARTED - add return value to function comment
298 UINT64 InterruptFlags
;
302 // Get address of bundle 0
304 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
306 if (IvtEntryTable
[ExceptionType
].RegisteredCallback
!= NULL
) {
308 // we've already installed to this vector
310 if (NewCallback
!= NULL
) {
312 // if the input handler is non-null, error
314 return EFI_ALREADY_STARTED
;
317 // else remove the previously installed handler
319 OldTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
320 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
321 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
322 UnchainExternalInterrupt ();
324 UnhookEntry (ExceptionType
);
327 ProgramInterruptFlags (InterruptFlags
);
328 gBS
->RestoreTPL (OldTpl
);
330 // re-init IvtEntryTable
332 gBS
->SetMem (&IvtEntryTable
[ExceptionType
], sizeof (IVT_ENTRY
), 0);
336 // no user handler installed on this vector
338 if (NewCallback
!= NULL
) {
339 OldTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
340 InterruptFlags
= ProgramInterruptFlags (DISABLE_INTERRUPTS
);
341 if (ExceptionType
== EXCEPT_IPF_EXTERNAL_INTERRUPT
) {
342 ChainExternalInterrupt (NewCallback
);
344 HookEntry (ExceptionType
, NewBundles
, NewCallback
);
347 ProgramInterruptFlags (InterruptFlags
);
348 gBS
->RestoreTPL (OldTpl
);
358 IN EFI_EXCEPTION_TYPE ExceptionType
,
359 IN BUNDLE NewBundles
[4],
360 IN
VOID (*NewCallback
) ()
365 Saves original IVT contents and inserts a few new bundles which are fixed up
366 to store the ExceptionType and then call the common handler.
369 IN EFI_EXCEPTION_TYPE ExceptionType,
370 IN BUNDLE NewBundles[4],
371 IN VOID (*NewCallback) ()
378 // TODO: ExceptionType - add argument and description to function comment
379 // TODO: ] - add argument and description to function comment
380 // TODO: ) - add argument and description to function comment
386 // Get address of bundle 0
388 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
391 // copy original bundles from IVT to IvtEntryTable so we can restore them later
394 IvtEntryTable
[ExceptionType
].OrigBundles
,
396 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
401 gBS
->CopyMem (B0Ptr
, NewBundles
, sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
);
404 // fixup IVT entry so it stores its index and whether or not to chain...
406 FixupBundle
= B0Ptr
+ 2;
407 FixupBundle
->high
|= ExceptionType
<< 36;
409 InstructionCacheFlush (B0Ptr
, 5);
410 IvtEntryTable
[ExceptionType
].RegisteredCallback
= NewCallback
;
416 IN EFI_EXCEPTION_TYPE ExceptionType
421 Restores original IVT contents when unregistering a callback function
424 IN EFI_EXCEPTION_TYPE ExceptionType,
431 // TODO: ExceptionType - add argument and description to function comment
436 // Get address of bundle 0
438 GetHandlerEntryPoint (ExceptionType
, (VOID
**) &B0Ptr
);
440 // restore original bundles in IVT
444 IvtEntryTable
[ExceptionType
].OrigBundles
,
445 sizeof (BUNDLE
) * NUM_BUNDLES_IN_STUB
447 InstructionCacheFlush (B0Ptr
, 5);
452 ChainExternalInterrupt (
453 IN
VOID (*NewCallback
) ()
458 Sets up cache flush and calls assembly function to chain external interrupt.
459 Records new callback in IvtEntryTable.
462 IN VOID (*NewCallback) ()
469 // TODO: ) - add argument and description to function comment
473 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
474 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NewCallback
;
476 InstructionCacheFlush (Start
, 0x400);
481 UnchainExternalInterrupt (
487 Sets up cache flush and calls assembly function to restore external interrupt.
488 Removes registered callback from IvtEntryTable.
501 Start
= (VOID
*) ((UINT8
*) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT
+ 0x400);
503 InstructionCacheFlush (Start
, 0x400);
504 IvtEntryTable
[EXCEPT_IPF_EXTERNAL_INTERRUPT
].RegisteredCallback
= NULL
;
508 // The rest of the functions in this file are all member functions for the
509 // DebugSupport protocol
514 GetMaximumProcessorIndex (
515 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
516 OUT UINTN
*MaxProcessorIndex
520 Routine Description: This is a DebugSupport protocol member function. Hard
521 coded to support only 1 processor for now.
525 Returns: Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0
528 // TODO: This - add argument and description to function comment
529 // TODO: MaxProcessorIndex - add argument and description to function comment
531 *MaxProcessorIndex
= 0;
532 return (EFI_SUCCESS
);
537 RegisterPeriodicCallback (
538 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
539 IN UINTN ProcessorIndex
,
540 IN EFI_PERIODIC_CALLBACK NewPeriodicCallback
545 DebugSupport protocol member function
548 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
549 IN UINTN ProcessorIndex,
550 IN EFI_PERIODIC_CALLBACK NewPeriodicCallback
554 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.
557 // TODO: This - add argument and description to function comment
558 // TODO: ProcessorIndex - add argument and description to function comment
559 // TODO: NewPeriodicCallback - add argument and description to function comment
561 return ManageIvtEntryTable (EXCEPT_IPF_EXTERNAL_INTERRUPT
, NULL
, NewPeriodicCallback
);
566 RegisterExceptionCallback (
567 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
568 IN UINTN ProcessorIndex
,
569 IN EFI_EXCEPTION_CALLBACK NewCallback
,
570 IN EFI_EXCEPTION_TYPE ExceptionType
575 DebugSupport protocol member function
578 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
579 IN EFI_EXCEPTION_CALLBACK NewCallback,
580 IN EFI_EXCEPTION_TYPE ExceptionType
584 EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered.
587 // TODO: This - add argument and description to function comment
588 // TODO: ProcessorIndex - add argument and description to function comment
589 // TODO: NewCallback - add argument and description to function comment
590 // TODO: ExceptionType - add argument and description to function comment
592 return ManageIvtEntryTable (
594 (BUNDLE
*) ((EFI_PLABEL
*) HookStub
)->EntryPoint
,
601 InvalidateInstructionCache (
602 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
603 IN UINTN ProcessorIndex
,
610 DebugSupport protocol member function. Calls assembly routine to flush cache.
618 // TODO: This - add argument and description to function comment
619 // TODO: ProcessorIndex - add argument and description to function comment
620 // TODO: Start - add argument and description to function comment
621 // TODO: Length - add argument and description to function comment
623 InstructionCacheFlush (Start
, Length
);
624 return (EFI_SUCCESS
);