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