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