]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/DebugSupportDxe/Ia32/PlDebugSupport.c
code scrub for DebugSpport Module.
[mirror_edk2.git] / MdeModulePkg / Universal / DebugSupportDxe / Ia32 / PlDebugSupport.c
... / ...
CommitLineData
1/** @file\r
2 Generic debug support functions for IA32/x64.\r
3\r
4Copyright (c) 2006 - 2008, Intel Corporation\r
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
15#include "DebugSupport.h"\r
16\r
17//\r
18// This the global main table to keep track of the interrupts\r
19//\r
20IDT_ENTRY *IdtEntryTable = NULL;\r
21IA32_IDT_GATE_DESCRIPTOR NullDesc = {0};\r
22\r
23/**\r
24 Read IDT Gate Descriptor from IDT Table.\r
25\r
26 @param Vector Specifies vector number.\r
27 @param IdtGateDescriptor Pointer to IDT Gate Descriptor read from IDT Table.\r
28\r
29**/\r
30VOID\r
31ReadIdtGateDescriptor (\r
32 IN EFI_EXCEPTION_TYPE Vector,\r
33 OUT IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor\r
34 )\r
35{\r
36 IA32_DESCRIPTOR IdtrValue;\r
37 IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
38\r
39 AsmReadIdtr (&IdtrValue);\r
40 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtrValue.Base;\r
41\r
42 CopyMem ((VOID *) IdtGateDescriptor, (VOID *) &(IdtTable)[Vector], sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
43}\r
44\r
45/**\r
46 Write IDT Gate Descriptor into IDT Table.\r
47\r
48 @param Vector Specifies vector number.\r
49 @param IdtGateDescriptor Pointer to IDT Gate Descriptor written into IDT Table.\r
50\r
51**/\r
52VOID\r
53WriteIdtGateDescriptor (\r
54 EFI_EXCEPTION_TYPE Vector,\r
55 IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor\r
56 )\r
57{\r
58 IA32_DESCRIPTOR IdtrValue;\r
59 IA32_IDT_GATE_DESCRIPTOR *IdtTable;\r
60\r
61 AsmReadIdtr (&IdtrValue);\r
62 IdtTable = (IA32_IDT_GATE_DESCRIPTOR *) IdtrValue.Base;\r
63\r
64 CopyMem ((VOID *) &(IdtTable)[Vector], (VOID *) IdtGateDescriptor, sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
65}\r
66\r
67/**\r
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
75 @param ExceptionType Specifies which vector to hook.\r
76 @param NewCallback A pointer to the new function to be registered.\r
77\r
78**/\r
79VOID\r
80HookEntry (\r
81 IN EFI_EXCEPTION_TYPE ExceptionType,\r
82 IN VOID (*NewCallback) ()\r
83 )\r
84{\r
85 BOOLEAN OldIntFlagState;\r
86\r
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
93\r
94 ReadIdtGateDescriptor (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc));\r
95 IdtEntryTable[ExceptionType].OrigVector = (DEBUG_PROC) GetInterruptHandleFromIdt (&(IdtEntryTable[ExceptionType].OrigDesc));\r
96\r
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
105\r
106 return ;\r
107}\r
108\r
109/**\r
110 Undoes HookEntry. This code executes in boot services context.\r
111\r
112 @param ExceptionType Specifies which entry to unhook\r
113\r
114**/\r
115VOID\r
116UnhookEntry (\r
117 IN EFI_EXCEPTION_TYPE ExceptionType\r
118 )\r
119{\r
120 BOOLEAN OldIntFlagState;\r
121\r
122 //\r
123 // Disables CPU interrupts and returns the previous interrupt state\r
124 //\r
125 OldIntFlagState = SaveAndDisableInterrupts ();\r
126\r
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
138}\r
139\r
140/**\r
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
145\r
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
151\r
152**/\r
153EFI_STATUS\r
154EFIAPI\r
155GetMaximumProcessorIndex (\r
156 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
157 OUT UINTN *MaxProcessorIndex\r
158 )\r
159{\r
160 *MaxProcessorIndex = 0;\r
161 return EFI_SUCCESS;\r
162}\r
163\r
164/**\r
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
177**/\r
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
185{\r
186 return ManageIdtEntryTable (PeriodicCallback, SYSTEM_TIMER_VECTOR);\r
187}\r
188\r
189/**\r
190 Registers a function to be called when a given processor exception occurs.\r
191\r
192 This code executes in boot services context.\r
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
205**/\r
206EFI_STATUS\r
207EFIAPI\r
208RegisterExceptionCallback (\r
209 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
210 IN UINTN ProcessorIndex,\r
211 IN EFI_EXCEPTION_CALLBACK ExceptionCallback,\r
212 IN EFI_EXCEPTION_TYPE ExceptionType\r
213 )\r
214{\r
215 return ManageIdtEntryTable (ExceptionCallback, ExceptionType);\r
216}\r
217\r
218/**\r
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
229\r
230**/\r
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
239{\r
240 AsmWbinvd ();\r
241 return EFI_SUCCESS;\r
242}\r
243\r
244/**\r
245 Common piece of code that invokes the registered handlers.\r
246\r
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
251\r
252**/\r
253VOID\r
254InterruptDistrubutionHub (\r
255 EFI_EXCEPTION_TYPE ExceptionType,\r
256 EFI_SYSTEM_CONTEXT_IA32 *ContextRecord\r
257 )\r
258{\r
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
265 }\r
266 }\r
267}\r
268\r
269/**\r
270 This is the callback that is written to the Loaded Image protocol instance\r
271 on the image handle. It uninstalls all registered handlers and frees all entry\r
272 stub memory.\r
273\r
274 @param ImageHandle The firmware allocated handle for the EFI image.\r
275\r
276 @retval EFI_SUCCESS Always.\r
277\r
278**/\r
279EFI_STATUS\r
280EFIAPI\r
281PlUnloadDebugSupportDriver (\r
282 IN EFI_HANDLE ImageHandle\r
283 )\r
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
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
295 }\r
296\r
297 FreePool (IdtEntryTable);\r
298\r
299 return EFI_SUCCESS;\r
300}\r
301\r
302/**\r
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
307\r
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
312\r
313**/\r
314EFI_STATUS\r
315PlInitializeDebugSupportDriver (\r
316 VOID\r
317 )\r
318{\r
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
351 }\r
352 }\r
353 FreePool (IdtEntryTable);\r
354\r
355 return EFI_OUT_OF_RESOURCES;\r
356}\r