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