]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/DebugSupportDxe/Ia32/PlDebugSupport.c
1. Merger generic functions into one file.
[mirror_edk2.git] / MdeModulePkg / Universal / DebugSupportDxe / Ia32 / PlDebugSupport.c
1 /** @file
2 IA32 specific debug support functions
3
4 Copyright (c) 2006 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT 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 //
23 IDT_ENTRY *IdtEntryTable = NULL;
24 IA32_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 **/
33 VOID 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 **/
53 VOID 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 **/
82 EFI_STATUS
83 HookEntry (
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 **/
115 EFI_STATUS
116 UnhookEntry (
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 **/
139 EFI_STATUS
140 EFIAPI
141 GetMaximumProcessorIndex (
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 **/
161 EFI_STATUS
162 EFIAPI
163 RegisterPeriodicCallback (
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 **/
186 EFI_STATUS
187 EFIAPI
188 RegisterExceptionCallback (
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 **/
209 EFI_STATUS
210 EFIAPI
211 InvalidateInstructionCache (
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 **/
234 EFI_STATUS
235 PlInitializeDebugSupportDriver (
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
260 ErrorCleanup:
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 **/
282 EFI_STATUS
283 EFIAPI
284 PlUnloadDebugSupportDriver (
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 **/
307 VOID
308 InterruptDistrubutionHub (
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 }