/** @file\r
- IA32 specific debug support functions\r
+ IA32/x64 generic functions to support Debug Support protocol.\r
\r
-Copyright (c) 2006 - 2008, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-//\r
-// private header files\r
-//\r
#include "DebugSupport.h"\r
\r
//\r
// This the global main table to keep track of the interrupts\r
//\r
-IDT_ENTRY *IdtEntryTable = NULL;\r
-IA32_IDT_GATE_DESCRIPTOR NullDesc = {0};\r
+IDT_ENTRY *IdtEntryTable = NULL;\r
\r
/**\r
Read IDT Gate Descriptor from IDT Table.\r
\r
@param Vector Specifies vector number.\r
- @param IdtGateDecriptor Pointer to IDT Gate Descriptor read from IDT Table.\r
+ @param IdtGateDescriptor Pointer to IDT Gate Descriptor read from IDT Table.\r
\r
**/\r
-VOID ReadIdtGateDecriptor (\r
+VOID\r
+ReadIdtGateDescriptor (\r
IN EFI_EXCEPTION_TYPE Vector,\r
- OUT IA32_IDT_GATE_DESCRIPTOR *IdtGateDecriptor\r
+ OUT IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor\r
)\r
{\r
- IA32_DESCRIPTOR IdtrValue;\r
- IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
+ IA32_DESCRIPTOR IdtrValue;\r
+ IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
\r
- AsmReadIdtr (&IdtrValue);\r
- IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtrValue.Base;\r
+ AsmReadIdtr (&IdtrValue);\r
+ IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)IdtrValue.Base;\r
\r
- CopyMem ((VOID *) IdtGateDecriptor, (VOID *) &(IdtTable)[Vector], sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
+ CopyMem ((VOID *)IdtGateDescriptor, (VOID *)&(IdtTable)[Vector], sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
}\r
+\r
/**\r
Write IDT Gate Descriptor into IDT Table.\r
\r
@param Vector Specifies vector number.\r
- @param IdtGateDecriptor Pointer to IDT Gate Descriptor written into IDT Table.\r
+ @param IdtGateDescriptor Pointer to IDT Gate Descriptor written into IDT Table.\r
\r
**/\r
-VOID WriteIdtGateDecriptor (\r
+VOID\r
+WriteIdtGateDescriptor (\r
EFI_EXCEPTION_TYPE Vector,\r
- IA32_IDT_GATE_DESCRIPTOR *IdtGateDecriptor\r
+ IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor\r
)\r
{\r
- IA32_DESCRIPTOR IdtrValue;\r
- IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
+ IA32_DESCRIPTOR IdtrValue;\r
+ IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
\r
- AsmReadIdtr (&IdtrValue);\r
- IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtrValue.Base;\r
+ AsmReadIdtr (&IdtrValue);\r
+ IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)IdtrValue.Base;\r
\r
- CopyMem ((VOID *) &(IdtTable)[Vector], (VOID *) IdtGateDecriptor, sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
+ CopyMem ((VOID *)&(IdtTable)[Vector], (VOID *)IdtGateDescriptor, sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
}\r
\r
-\r
/**\r
Creates a nes entry stub. Then saves the current IDT entry and replaces it\r
with an interrupt gate for the new entry point. The IdtEntryTable is updated\r
@param ExceptionType Specifies which vector to hook.\r
@param NewCallback A pointer to the new function to be registered.\r
\r
- @retval EFI_SUCCESS Always.\r
-\r
**/\r
-EFI_STATUS\r
+VOID\r
HookEntry (\r
- IN EFI_EXCEPTION_TYPE ExceptionType,\r
- IN VOID (*NewCallback) ()\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN CALLBACK_FUNC NewCallback\r
)\r
{\r
- BOOLEAN OldIntFlagState;\r
- EFI_STATUS Status;\r
-\r
- Status = CreateEntryStub (ExceptionType, (VOID **) &IdtEntryTable[ExceptionType].StubEntry);\r
- if (Status == EFI_SUCCESS) {\r
- OldIntFlagState = WriteInterruptFlag (0);\r
- ReadIdtGateDecriptor (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
-\r
- IdtEntryTable[ExceptionType].OrigVector = (DEBUG_PROC) GetProcedureEntryPoint (&(IdtEntryTable[ExceptionType].OrigDesc));\r
-\r
- Vect2Desc (&IdtEntryTable[ExceptionType].NewDesc, IdtEntryTable[ExceptionType].StubEntry);\r
- IdtEntryTable[ExceptionType].RegisteredCallback = NewCallback;\r
- WriteIdtGateDecriptor (ExceptionType, &(IdtEntryTable[ExceptionType].NewDesc));\r
- WriteInterruptFlag (OldIntFlagState);\r
- }\r
-\r
- return Status;\r
+ BOOLEAN OldIntFlagState;\r
+\r
+ CreateEntryStub (ExceptionType, (VOID **)&IdtEntryTable[ExceptionType].StubEntry);\r
+\r
+ //\r
+ // Disables CPU interrupts and returns the previous interrupt state\r
+ //\r
+ OldIntFlagState = SaveAndDisableInterrupts ();\r
+\r
+ //\r
+ // gets IDT Gate descriptor by index\r
+ //\r
+ ReadIdtGateDescriptor (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
+ //\r
+ // stores orignal interrupt handle\r
+ //\r
+ IdtEntryTable[ExceptionType].OrigVector = (DEBUG_PROC)GetInterruptHandleFromIdt (&(IdtEntryTable[ExceptionType].OrigDesc));\r
+\r
+ //\r
+ // encodes new IDT Gate descriptor by stub entry\r
+ //\r
+ Vect2Desc (&IdtEntryTable[ExceptionType].NewDesc, IdtEntryTable[ExceptionType].StubEntry);\r
+ //\r
+ // stores NewCallback\r
+ //\r
+ IdtEntryTable[ExceptionType].RegisteredCallback = NewCallback;\r
+\r
+ //\r
+ // writes back new IDT Gate descriptor\r
+ //\r
+ WriteIdtGateDescriptor (ExceptionType, &(IdtEntryTable[ExceptionType].NewDesc));\r
+\r
+ //\r
+ // restore interrupt state\r
+ //\r
+ SetInterruptState (OldIntFlagState);\r
+\r
+ return;\r
}\r
\r
/**\r
\r
@param ExceptionType Specifies which entry to unhook\r
\r
- @retval EFI_SUCCESS Always.\r
-\r
**/\r
-EFI_STATUS\r
+VOID\r
UnhookEntry (\r
- IN EFI_EXCEPTION_TYPE ExceptionType\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
)\r
{\r
- BOOLEAN OldIntFlagState;\r
+ BOOLEAN OldIntFlagState;\r
\r
- OldIntFlagState = WriteInterruptFlag (0);\r
- WriteIdtGateDecriptor (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
- WriteInterruptFlag (OldIntFlagState);\r
+ //\r
+ // Disables CPU interrupts and returns the previous interrupt state\r
+ //\r
+ OldIntFlagState = SaveAndDisableInterrupts ();\r
\r
- return EFI_SUCCESS;\r
+ //\r
+ // restore the default IDT Date Descriptor\r
+ //\r
+ WriteIdtGateDescriptor (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
+\r
+ //\r
+ // restore interrupt state\r
+ //\r
+ SetInterruptState (OldIntFlagState);\r
+\r
+ return;\r
}\r
\r
/**\r
- This is a DebugSupport protocol member function, hard\r
- coded to support only 1 processor for now.\r
+ Returns the maximum value that may be used for the ProcessorIndex parameter in\r
+ RegisterPeriodicCallback() and RegisterExceptionCallback().\r
+\r
+ Hard coded to support only 1 processor for now.\r
\r
- @param This The DebugSupport instance\r
- @param MaxProcessorIndex The maximuim supported processor index\r
+ @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.\r
+ @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the maximum supported\r
+ processor index is returned. Always 0 returned.\r
\r
- @retval EFI_SUCCESS Always returned with **MaxProcessorIndex set to 0.\r
+ @retval EFI_SUCCESS Always returned with **MaxProcessorIndex set to 0.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
GetMaximumProcessorIndex (\r
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
- OUT UINTN *MaxProcessorIndex\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ OUT UINTN *MaxProcessorIndex\r
)\r
{\r
*MaxProcessorIndex = 0;\r
- return (EFI_SUCCESS);\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
- DebugSupport protocol member function.\r
-\r
- @param This The DebugSupport instance\r
- @param ProcessorIndex Which processor the callback applies to.\r
- @param PeriodicCallback Callback function\r
-\r
- @retval EFI_SUCCESS Indicates the callback was registered.\r
- @retval others Callback was not registered.\r
-\r
+ Registers a function to be called back periodically in interrupt context.\r
+\r
+ @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.\r
+ @param ProcessorIndex Specifies which processor the callback function applies to.\r
+ @param PeriodicCallback A pointer to a function of type PERIODIC_CALLBACK that is the main\r
+ periodic entry point of the debug agent.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback\r
+ function was previously registered.\r
+ @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback\r
+ function.\r
**/\r
EFI_STATUS\r
EFIAPI\r
RegisterPeriodicCallback (\r
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
- IN UINTN ProcessorIndex,\r
- IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
)\r
{\r
return ManageIdtEntryTable (PeriodicCallback, SYSTEM_TIMER_VECTOR);\r
}\r
\r
/**\r
- DebugSupport protocol member function.\r
+ Registers a function to be called when a given processor exception occurs.\r
\r
This code executes in boot services context.\r
\r
- @param This The DebugSupport instance\r
- @param ProcessorIndex Which processor the callback applies to.\r
- @param NewCallback Callback function\r
- @param ExceptionType Which exception to hook\r
-\r
- @retval EFI_SUCCESS Indicates the callback was registered.\r
- @retval others Callback was not registered.\r
-\r
+ @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.\r
+ @param ProcessorIndex Specifies which processor the callback function applies to.\r
+ @param ExceptionCallback A pointer to a function of type EXCEPTION_CALLBACK that is called\r
+ when the processor exception specified by ExceptionType occurs.\r
+ @param ExceptionType Specifies which processor exception to hook.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback\r
+ function was previously registered.\r
+ @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback\r
+ function.\r
**/\r
EFI_STATUS\r
EFIAPI\r
RegisterExceptionCallback (\r
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
- IN UINTN ProcessorIndex,\r
- IN EFI_EXCEPTION_CALLBACK NewCallback,\r
- IN EFI_EXCEPTION_TYPE ExceptionType\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN EFI_EXCEPTION_CALLBACK ExceptionCallback,\r
+ IN EFI_EXCEPTION_TYPE ExceptionType\r
)\r
{\r
- return ManageIdtEntryTable (NewCallback, ExceptionType);\r
+ return ManageIdtEntryTable (ExceptionCallback, ExceptionType);\r
}\r
\r
/**\r
- DebugSupport protocol member function. Calls assembly routine to flush cache.\r
+ Invalidates processor instruction cache for a memory range. Subsequent execution in this range\r
+ causes a fresh memory fetch to retrieve code to be executed.\r
\r
- @param This The DebugSupport instance\r
- @param ProcessorIndex Which processor the callback applies to.\r
- @param Start Physical base of the memory range to be invalidated\r
- @param Length mininum number of bytes in instruction cache to invalidate\r
+ @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance.\r
+ @param ProcessorIndex Specifies which processor's instruction cache is to be invalidated.\r
+ @param Start Specifies the physical base of the memory range to be invalidated.\r
+ @param Length Specifies the minimum number of bytes in the processor's instruction\r
+ cache to invalidate.\r
\r
- @retval EFI_SUCCESS Always returned.\r
+ @retval EFI_SUCCESS Always returned.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
InvalidateInstructionCache (\r
- IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
- IN UINTN ProcessorIndex,\r
- IN VOID *Start,\r
- IN UINT64 Length\r
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
+ IN UINTN ProcessorIndex,\r
+ IN VOID *Start,\r
+ IN UINT64 Length\r
)\r
{\r
AsmWbinvd ();\r
}\r
\r
/**\r
- Initializes driver's handler registration databas. \r
- \r
- This code executes in boot services context\r
- Must be public because it's referenced from DebugSupport.c\r
+ Common piece of code that invokes the registered handlers.\r
\r
- @retval EFI_UNSUPPORTED If IA32 processor does not support FXSTOR/FXRSTOR instructions,\r
- the context save will fail, so these processor's are not supported.\r
- @retval EFI_OUT_OF_RESOURCES Fails to allocate memory.\r
- @retval EFI_SUCCESS Initializes successfully.\r
+ This code executes in exception context so no efi calls are allowed.\r
+ This code is called from assembly file.\r
+\r
+ @param ExceptionType Exception type\r
+ @param ContextRecord System context\r
\r
**/\r
-EFI_STATUS\r
-PlInitializeDebugSupportDriver (\r
- VOID\r
+VOID\r
+InterruptDistrubutionHub (\r
+ EFI_EXCEPTION_TYPE ExceptionType,\r
+ EFI_SYSTEM_CONTEXT_IA32 *ContextRecord\r
)\r
{\r
- EFI_EXCEPTION_TYPE ExceptionType;\r
-\r
- if (!FxStorSupport ()) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- IdtEntryTable = AllocateZeroPool (sizeof (IDT_ENTRY) * NUM_IDT_ENTRIES);\r
- if (IdtEntryTable == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
- IdtEntryTable[ExceptionType].StubEntry = (DEBUG_PROC) (UINTN) AllocatePool (StubSize);\r
- if (IdtEntryTable[ExceptionType].StubEntry == NULL) {\r
- goto ErrorCleanup;\r
- }\r
-\r
- CopyMem ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry, InterruptEntryStub, StubSize);\r
- }\r
- return EFI_SUCCESS;\r
-\r
-ErrorCleanup:\r
-\r
- for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
- if (IdtEntryTable[ExceptionType].StubEntry != NULL) {\r
- FreePool ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry);\r
+ if (IdtEntryTable[ExceptionType].RegisteredCallback != NULL) {\r
+ if (ExceptionType != SYSTEM_TIMER_VECTOR) {\r
+ IdtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, ContextRecord);\r
+ } else {\r
+ OrigVector = IdtEntryTable[ExceptionType].OrigVector;\r
+ IdtEntryTable[ExceptionType].RegisteredCallback (ContextRecord);\r
}\r
}\r
- FreePool (IdtEntryTable);\r
-\r
- return EFI_OUT_OF_RESOURCES;\r
}\r
\r
/**\r
- This is the callback that is written to the LoadedImage protocol instance\r
+ This is the callback that is written to the Loaded Image protocol instance\r
on the image handle. It uninstalls all registered handlers and frees all entry\r
stub memory.\r
\r
EFI_STATUS\r
EFIAPI\r
PlUnloadDebugSupportDriver (\r
- IN EFI_HANDLE ImageHandle\r
+ IN EFI_HANDLE ImageHandle\r
)\r
{\r
EFI_EXCEPTION_TYPE ExceptionType;\r
\r
for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
ManageIdtEntryTable (NULL, ExceptionType);\r
+ //\r
+ // Free space for each Interrupt Stub precedure.\r
+ //\r
+ if (IdtEntryTable[ExceptionType].StubEntry != NULL) {\r
+ FreePool ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry);\r
+ }\r
}\r
\r
FreePool (IdtEntryTable);\r
+\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Common piece of code that invokes the registered handlers.\r
+ Initializes driver's handler registration database.\r
\r
- This code executes in exception context so no efi calls are allowed.\r
+ This code executes in boot services context.\r
+ Must be public because it's referenced from DebugSupport.c\r
\r
- @param ExceptionType Exception type\r
- @param ContextRecord System context\r
+ @retval EFI_UNSUPPORTED If IA32/x64 processor does not support FXSTOR/FXRSTOR instructions,\r
+ the context save will fail, so these processors are not supported.\r
+ @retval EFI_OUT_OF_RESOURCES Fails to allocate memory.\r
+ @retval EFI_SUCCESS Initializes successfully.\r
\r
**/\r
-VOID\r
-InterruptDistrubutionHub (\r
- EFI_EXCEPTION_TYPE ExceptionType,\r
- EFI_SYSTEM_CONTEXT_IA32 *ContextRecord\r
+EFI_STATUS\r
+PlInitializeDebugSupportDriver (\r
+ VOID\r
)\r
{\r
- if (IdtEntryTable[ExceptionType].RegisteredCallback != NULL) {\r
- if (ExceptionType != SYSTEM_TIMER_VECTOR) {\r
- IdtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, ContextRecord);\r
- } else {\r
- OrigVector = IdtEntryTable[ExceptionType].OrigVector;\r
- IdtEntryTable[ExceptionType].RegisteredCallback (ContextRecord);\r
+ EFI_EXCEPTION_TYPE ExceptionType;\r
+\r
+ //\r
+ // Check whether FxStor instructions are supported.\r
+ //\r
+ if (!FxStorSupport ()) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ IdtEntryTable = AllocateZeroPool (sizeof (IDT_ENTRY) * NUM_IDT_ENTRIES);\r
+ if (IdtEntryTable == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
+ IdtEntryTable[ExceptionType].StubEntry = (DEBUG_PROC)(UINTN)AllocatePool (StubSize);\r
+ if (IdtEntryTable[ExceptionType].StubEntry == NULL) {\r
+ goto ErrorCleanup;\r
+ }\r
+\r
+ //\r
+ // Copy Interrupt stub code.\r
+ //\r
+ CopyMem ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry, InterruptEntryStub, StubSize);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ErrorCleanup:\r
+\r
+ for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) {\r
+ if (IdtEntryTable[ExceptionType].StubEntry != NULL) {\r
+ FreePool ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry);\r
}\r
}\r
+\r
+ FreePool (IdtEntryTable);\r
+\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r