PlDebugSupport.c revision 6e8a984eca4c9763038e887b8d813b2110bbaed6
1/** @file 2 IA32 specific debug support functions 3 4Copyright (c) 2006 - 2008, Intel Corporation 5All rights reserved. This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13**/ 14 15// 16// private header files 17// 18#include "DebugSupport.h" 19 20// 21// This the global main table to keep track of the interrupts 22// 23IDT_ENTRY *IdtEntryTable = NULL; 24IA32_IDT_GATE_DESCRIPTOR NullDesc = {0}; 25 26/** 27 Read IDT Gate Descriptor from IDT Table. 28 29 @param Vector Specifies vector number. 30 @param IdtGateDecriptor Pointer to IDT Gate Descriptor read from IDT Table. 31 32**/ 33VOID ReadIdtGateDecriptor ( 34 IN EFI_EXCEPTION_TYPE Vector, 35 OUT IA32_IDT_GATE_DESCRIPTOR *IdtGateDecriptor 36 ) 37{ 38 IA32_DESCRIPTOR IdtrValue; 39 IA32_IDT_GATE_DESCRIPTOR *IdtTable; 40 41 AsmReadIdtr (&IdtrValue); 42 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtrValue.Base; 43 44 CopyMem ((VOID *) IdtGateDecriptor, (VOID *) &(IdtTable)[Vector], sizeof (IA32_IDT_GATE_DESCRIPTOR)); 45} 46/** 47 Write IDT Gate Descriptor into IDT Table. 48 49 @param Vector Specifies vector number. 50 @param IdtGateDecriptor Pointer to IDT Gate Descriptor written into IDT Table. 51 52**/ 53VOID WriteIdtGateDecriptor ( 54 EFI_EXCEPTION_TYPE Vector, 55 IA32_IDT_GATE_DESCRIPTOR *IdtGateDecriptor 56 ) 57{ 58 IA32_DESCRIPTOR IdtrValue; 59 IA32_IDT_GATE_DESCRIPTOR *IdtTable; 60 61 AsmReadIdtr (&IdtrValue); 62 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtrValue.Base; 63 64 CopyMem ((VOID *) &(IdtTable)[Vector], (VOID *) IdtGateDecriptor, sizeof (IA32_IDT_GATE_DESCRIPTOR)); 65} 66 67 68/** 69 Creates a nes entry stub. Then saves the current IDT entry and replaces it 70 with an interrupt gate for the new entry point. The IdtEntryTable is updated 71 with the new registered function. 72 73 This code executes in boot services context. The stub entry executes in interrupt 74 context. 75 76 @param ExceptionType Specifies which vector to hook. 77 @param NewCallback A pointer to the new function to be registered. 78 79 @retval EFI_SUCCESS Always. 80 81**/ 82EFI_STATUS 83HookEntry ( 84 IN EFI_EXCEPTION_TYPE ExceptionType, 85 IN VOID (*NewCallback) () 86 ) 87{ 88 BOOLEAN OldIntFlagState; 89 EFI_STATUS Status; 90 91 Status = CreateEntryStub (ExceptionType, (VOID **) &IdtEntryTable[ExceptionType].StubEntry); 92 if (Status == EFI_SUCCESS) { 93 OldIntFlagState = WriteInterruptFlag (0); 94 ReadIdtGateDecriptor (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc)); 95 96 IdtEntryTable[ExceptionType].OrigVector = (DEBUG_PROC) GetProcedureEntryPoint (&(IdtEntryTable[ExceptionType].OrigDesc)); 97 98 Vect2Desc (&IdtEntryTable[ExceptionType].NewDesc, IdtEntryTable[ExceptionType].StubEntry); 99 IdtEntryTable[ExceptionType].RegisteredCallback = NewCallback; 100 WriteIdtGateDecriptor (ExceptionType, &(IdtEntryTable[ExceptionType].NewDesc)); 101 WriteInterruptFlag (OldIntFlagState); 102 } 103 104 return Status; 105} 106 107/** 108 Undoes HookEntry. This code executes in boot services context. 109 110 @param ExceptionType Specifies which entry to unhook 111 112 @retval EFI_SUCCESS Always. 113 114**/ 115EFI_STATUS 116UnhookEntry ( 117 IN EFI_EXCEPTION_TYPE ExceptionType 118 ) 119{ 120 BOOLEAN OldIntFlagState; 121 122 OldIntFlagState = WriteInterruptFlag (0); 123 WriteIdtGateDecriptor (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc)); 124 WriteInterruptFlag (OldIntFlagState); 125 126 return EFI_SUCCESS; 127} 128 129/** 130 This is a DebugSupport protocol member function, hard 131 coded to support only 1 processor for now. 132 133 @param This The DebugSupport instance 134 @param MaxProcessorIndex The maximuim supported processor index 135 136 @retval EFI_SUCCESS Always returned with **MaxProcessorIndex set to 0. 137 138**/ 139EFI_STATUS 140EFIAPI 141GetMaximumProcessorIndex ( 142 IN EFI_DEBUG_SUPPORT_PROTOCOL *This, 143 OUT UINTN *MaxProcessorIndex 144 ) 145{ 146 *MaxProcessorIndex = 0; 147 return (EFI_SUCCESS); 148} 149 150/** 151 DebugSupport protocol member function. 152 153 @param This The DebugSupport instance 154 @param ProcessorIndex Which processor the callback applies to. 155 @param PeriodicCallback Callback function 156 157 @retval EFI_SUCCESS Indicates the callback was registered. 158 @retval others Callback was not registered. 159 160**/ 161EFI_STATUS 162EFIAPI 163RegisterPeriodicCallback ( 164 IN EFI_DEBUG_SUPPORT_PROTOCOL *This, 165 IN UINTN ProcessorIndex, 166 IN EFI_PERIODIC_CALLBACK PeriodicCallback 167 ) 168{ 169 return ManageIdtEntryTable (PeriodicCallback, SYSTEM_TIMER_VECTOR); 170} 171 172/** 173 DebugSupport protocol member function. 174 175 This code executes in boot services context. 176 177 @param This The DebugSupport instance 178 @param ProcessorIndex Which processor the callback applies to. 179 @param NewCallback Callback function 180 @param ExceptionType Which exception to hook 181 182 @retval EFI_SUCCESS Indicates the callback was registered. 183 @retval others Callback was not registered. 184 185**/ 186EFI_STATUS 187EFIAPI 188RegisterExceptionCallback ( 189 IN EFI_DEBUG_SUPPORT_PROTOCOL *This, 190 IN UINTN ProcessorIndex, 191 IN EFI_EXCEPTION_CALLBACK NewCallback, 192 IN EFI_EXCEPTION_TYPE ExceptionType 193 ) 194{ 195 return ManageIdtEntryTable (NewCallback, ExceptionType); 196} 197 198/** 199 DebugSupport protocol member function. Calls assembly routine to flush cache. 200 201 @param This The DebugSupport instance 202 @param ProcessorIndex Which processor the callback applies to. 203 @param Start Physical base of the memory range to be invalidated 204 @param Length mininum number of bytes in instruction cache to invalidate 205 206 @retval EFI_SUCCESS Always returned. 207 208**/ 209EFI_STATUS 210EFIAPI 211InvalidateInstructionCache ( 212 IN EFI_DEBUG_SUPPORT_PROTOCOL *This, 213 IN UINTN ProcessorIndex, 214 IN VOID *Start, 215 IN UINT64 Length 216 ) 217{ 218 AsmWbinvd (); 219 return EFI_SUCCESS; 220} 221 222/** 223 Initializes driver's handler registration databas. 224 225 This code executes in boot services context 226 Must be public because it's referenced from DebugSupport.c 227 228 @retval EFI_UNSUPPORTED If IA32 processor does not support FXSTOR/FXRSTOR instructions, 229 the context save will fail, so these processor's are not supported. 230 @retval EFI_OUT_OF_RESOURCES Fails to allocate memory. 231 @retval EFI_SUCCESS Initializes successfully. 232 233**/ 234EFI_STATUS 235PlInitializeDebugSupportDriver ( 236 VOID 237 ) 238{ 239 EFI_EXCEPTION_TYPE ExceptionType; 240 241 if (!FxStorSupport ()) { 242 return EFI_UNSUPPORTED; 243 } 244 245 IdtEntryTable = AllocateZeroPool (sizeof (IDT_ENTRY) * NUM_IDT_ENTRIES); 246 if (IdtEntryTable == NULL) { 247 return EFI_OUT_OF_RESOURCES; 248 } 249 250 for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) { 251 IdtEntryTable[ExceptionType].StubEntry = (DEBUG_PROC) (UINTN) AllocatePool (StubSize); 252 if (IdtEntryTable[ExceptionType].StubEntry == NULL) { 253 goto ErrorCleanup; 254 } 255 256 CopyMem ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry, InterruptEntryStub, StubSize); 257 } 258 return EFI_SUCCESS; 259 260ErrorCleanup: 261 262 for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) { 263 if (IdtEntryTable[ExceptionType].StubEntry != NULL) { 264 FreePool ((VOID *)(UINTN)IdtEntryTable[ExceptionType].StubEntry); 265 } 266 } 267 FreePool (IdtEntryTable); 268 269 return EFI_OUT_OF_RESOURCES; 270} 271 272/** 273 This is the callback that is written to the LoadedImage protocol instance 274 on the image handle. It uninstalls all registered handlers and frees all entry 275 stub memory. 276 277 @param ImageHandle The firmware allocated handle for the EFI image. 278 279 @retval EFI_SUCCESS Always. 280 281**/ 282EFI_STATUS 283EFIAPI 284PlUnloadDebugSupportDriver ( 285 IN EFI_HANDLE ImageHandle 286 ) 287{ 288 EFI_EXCEPTION_TYPE ExceptionType; 289 290 for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) { 291 ManageIdtEntryTable (NULL, ExceptionType); 292 } 293 294 FreePool (IdtEntryTable); 295 return EFI_SUCCESS; 296} 297 298/** 299 Common piece of code that invokes the registered handlers. 300 301 This code executes in exception context so no efi calls are allowed. 302 303 @param ExceptionType Exception type 304 @param ContextRecord System context 305 306**/ 307VOID 308InterruptDistrubutionHub ( 309 EFI_EXCEPTION_TYPE ExceptionType, 310 EFI_SYSTEM_CONTEXT_IA32 *ContextRecord 311 ) 312{ 313 if (IdtEntryTable[ExceptionType].RegisteredCallback != NULL) { 314 if (ExceptionType != SYSTEM_TIMER_VECTOR) { 315 IdtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, ContextRecord); 316 } else { 317 OrigVector = IdtEntryTable[ExceptionType].OrigVector; 318 IdtEntryTable[ExceptionType].RegisteredCallback (ContextRecord); 319 } 320 } 321} 322