]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgent/SmmDebugAgentLib.c
SourceLevelDebugPkg: Clean up source files
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / SmmDebugAgent / SmmDebugAgentLib.c
CommitLineData
18b144ea 1/** @file\r
2 Debug Agent library implementition.\r
3\r
77695f4d 4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>\r
18b144ea 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "SmmDebugAgentLib.h"\r
16\r
17DEBUG_AGENT_MAILBOX *mMailboxPointer = NULL;\r
b6ee5898 18DEBUG_AGENT_MAILBOX mLocalMailbox;\r
19UINTN mSavedDebugRegisters[6];\r
b422b62c 20IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33];\r
21BOOLEAN mSkipBreakpoint = FALSE;\r
6fee83fb 22BOOLEAN mSmmDebugIdtInitFlag = FALSE;\r
222c4930
LG
23BOOLEAN mApicTimerRestore = FALSE;\r
24BOOLEAN mPeriodicMode;\r
25UINT32 mTimerCycle;\r
26UINTN mApicTimerDivisor;\r
27UINT8 mVector;\r
b422b62c 28\r
29CHAR8 mWarningMsgIgnoreSmmEntryBreak[] = "Ignore smmentrybreak setting for SMI issued during DXE debugging!\r\n";\r
30\r
31/**\r
32 Check if debug agent support multi-processor.\r
33\r
34 @retval TRUE Multi-processor is supported.\r
35 @retval FALSE Multi-processor is not supported.\r
36\r
37**/\r
38BOOLEAN\r
39MultiProcessorDebugSupport (\r
40 VOID\r
41 )\r
42{\r
43 return FALSE;\r
44}\r
18b144ea 45\r
93c0bdec 46/**\r
47 Read the Attach/Break-in symbols from the debug port.\r
48\r
49 @param[in] Handle Pointer to Debug Port handle.\r
50 @param[out] BreakSymbol Returned break symbol.\r
51\r
52 @retval EFI_SUCCESS Read the symbol in BreakSymbol.\r
53 @retval EFI_NOT_FOUND No read the break symbol.\r
54\r
55**/\r
56EFI_STATUS\r
57DebugReadBreakSymbol (\r
58 IN DEBUG_PORT_HANDLE Handle,\r
59 OUT UINT8 *BreakSymbol\r
60 )\r
61{\r
62 //\r
63 // Smm instance has no debug timer to poll break symbol.\r
64 //\r
65 return EFI_NOT_FOUND;\r
66}\r
18b144ea 67\r
b422b62c 68/**\r
69 Get the pointer to Mailbox from the GUIDed HOB.\r
70\r
71 @return Pointer to Mailbox.\r
72\r
73**/\r
74DEBUG_AGENT_MAILBOX *\r
75GetMailboxFromHob (\r
76 VOID\r
77 )\r
78{\r
79 EFI_HOB_GUID_TYPE *GuidHob;\r
77695f4d 80 UINT64 *MailboxLocation;\r
b422b62c 81 DEBUG_AGENT_MAILBOX *Mailbox;\r
82\r
83 GuidHob = GetFirstGuidHob (&gEfiDebugAgentGuid);\r
84 if (GuidHob == NULL) {\r
85 return NULL;\r
86 }\r
87 MailboxLocation = (UINT64 *) (GET_GUID_HOB_DATA(GuidHob));\r
88 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
89 VerifyMailboxChecksum (Mailbox);\r
77695f4d 90\r
b422b62c 91 return Mailbox;\r
92}\r
93\r
18b144ea 94/**\r
95 Get Debug Agent Mailbox pointer.\r
96\r
97 @return Mailbox pointer.\r
98\r
99**/\r
100DEBUG_AGENT_MAILBOX *\r
101GetMailboxPointer (\r
102 VOID\r
103 )\r
104{\r
b422b62c 105 VerifyMailboxChecksum (mMailboxPointer);\r
18b144ea 106 return mMailboxPointer;\r
107}\r
108\r
109/**\r
110 Get debug port handle.\r
111\r
112 @return Debug port handle.\r
113\r
114**/\r
115DEBUG_PORT_HANDLE\r
116GetDebugPortHandle (\r
117 VOID\r
118 )\r
119{\r
b422b62c 120 return (DEBUG_PORT_HANDLE) (UINTN)(GetMailboxPointer()->DebugPortHandle);\r
18b144ea 121}\r
122\r
123/**\r
124 Store debug register when SMI exit.\r
125\r
126**/\r
127VOID\r
128SaveDebugRegister (\r
129 VOID\r
130 )\r
131{\r
132 mSavedDebugRegisters[0] = AsmReadDr0 ();\r
133 mSavedDebugRegisters[1] = AsmReadDr1 ();\r
134 mSavedDebugRegisters[2] = AsmReadDr2 ();\r
135 mSavedDebugRegisters[3] = AsmReadDr3 ();\r
136 mSavedDebugRegisters[4] = AsmReadDr6 ();\r
137 mSavedDebugRegisters[5] = AsmReadDr7 ();\r
138}\r
139\r
140/**\r
141 Restore debug register when SMI exit.\r
142\r
143**/\r
144VOID\r
145RestoreDebugRegister (\r
146 VOID\r
147 )\r
148{\r
149 AsmWriteDr7 (0);\r
150 AsmWriteDr0 (mSavedDebugRegisters[0]);\r
151 AsmWriteDr1 (mSavedDebugRegisters[1]);\r
152 AsmWriteDr2 (mSavedDebugRegisters[2]);\r
153 AsmWriteDr3 (mSavedDebugRegisters[3]);\r
154 AsmWriteDr6 (mSavedDebugRegisters[4]);\r
155 AsmWriteDr7 (mSavedDebugRegisters[5]);\r
156}\r
157\r
158/**\r
159 Initialize debug agent.\r
160\r
161 This function is used to set up debug enviroment for source level debug\r
162 in SMM code.\r
163\r
164 If InitFlag is DEBUG_AGENT_INIT_SMM, it will overirde IDT table entries\r
165 and initialize debug port. It will get debug agent Mailbox from GUIDed HOB,\r
166 it it exists, debug agent wiil copied it into the local Mailbox in SMM space.\r
167 it will overirde IDT table entries and initialize debug port. Context will be\r
168 NULL.\r
169 If InitFlag is DEBUG_AGENT_INIT_ENTER_SMI, debug agent will save Debug\r
170 Registers and get local Mailbox in SMM space. Context will be NULL.\r
171 If InitFlag is DEBUG_AGENT_INIT_EXIT_SMI, debug agent will restore Debug\r
172 Registers. Context will be NULL.\r
173\r
174 @param[in] InitFlag Init flag is used to decide initialize process.\r
175 @param[in] Context Context needed according to InitFlag.\r
176 @param[in] Function Continue function called by debug agent library; it was\r
177 optional.\r
178\r
179**/\r
180VOID\r
181EFIAPI\r
182InitializeDebugAgent (\r
183 IN UINT32 InitFlag,\r
184 IN VOID *Context, OPTIONAL\r
185 IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
186 )\r
187{\r
b422b62c 188 EFI_STATUS Status;\r
189 UINT64 DebugPortHandle;\r
190 IA32_IDT_GATE_DESCRIPTOR IdtEntry[33];\r
191 IA32_DESCRIPTOR IdtDescriptor;\r
192 IA32_DESCRIPTOR *Ia32Idtr;\r
193 IA32_IDT_ENTRY *Ia32IdtEntry;\r
194 IA32_DESCRIPTOR Idtr;\r
195 UINT16 IdtEntryCount;\r
196 DEBUG_AGENT_MAILBOX *Mailbox;\r
197 UINT64 *MailboxLocation;\r
08021523 198 UINT32 DebugTimerFrequency;\r
18b144ea 199\r
200 switch (InitFlag) {\r
201 case DEBUG_AGENT_INIT_SMM:\r
8cc26df4
JF
202 //\r
203 // Install configuration table for persisted vector handoff info\r
204 //\r
205 Status = gSmst->SmmInstallConfigurationTable (\r
206 gSmst,\r
207 &gEfiVectorHandoffTableGuid,\r
208 (VOID *) &mVectorHandoffInfoDebugAgent[0],\r
209 sizeof (EFI_VECTOR_HANDOFF_INFO) * mVectorHandoffInfoCount\r
210 );\r
211 if (EFI_ERROR (Status)) {\r
212 DEBUG ((EFI_D_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n"));\r
213 CpuDeadLoop ();\r
214 }\r
b422b62c 215 //\r
216 // Check if Debug Agent initialized in DXE phase\r
217 //\r
218 Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &Mailbox);\r
219 if (Status == EFI_SUCCESS && Mailbox != NULL) {\r
220 VerifyMailboxChecksum (Mailbox);\r
221 mMailboxPointer = Mailbox;\r
222 break;\r
18b144ea 223 }\r
b422b62c 224 //\r
225 // Check if Debug Agent initialized in SEC/PEI phase\r
226 //\r
77695f4d 227 Mailbox = GetMailboxFromHob ();\r
b422b62c 228 if (Mailbox != NULL) {\r
229 mMailboxPointer = Mailbox;\r
230 break;\r
231 }\r
232 //\r
8cc26df4 233 // Debug Agent was not initialized before, use the local mailbox.\r
b422b62c 234 //\r
235 ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
236 Mailbox = &mLocalMailbox;\r
237 //\r
238 // Save original IDT entries\r
239 //\r
77695f4d 240 AsmReadIdtr (&IdtDescriptor);\r
b422b62c 241 CopyMem (&IdtEntry, (VOID *)IdtDescriptor.Base, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR));\r
242 //\r
243 // Initialized Debug Agent\r
244 //\r
245 InitializeDebugIdt ();\r
08021523
JF
246 //\r
247 // Initialize Debug Timer hardware and save its frequency\r
248 //\r
86d13652 249 InitializeDebugTimer (&DebugTimerFrequency, TRUE);\r
f3ee38dd 250 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);\r
08021523 251\r
b422b62c 252 DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE) (UINTN)Mailbox->DebugPortHandle, NULL);\r
253 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
254 mMailboxPointer = Mailbox;\r
255 //\r
256 // Trigger one software interrupt to inform HOST\r
257 //\r
258 TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);\r
259\r
260 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
261 //\r
262 // Memory has been ready\r
263 //\r
264 if (IsHostAttached ()) {\r
265 //\r
266 // Trigger one software interrupt to inform HOST\r
267 //\r
268 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
269 }\r
270 //\r
271 // Find and report PE/COFF image info to HOST\r
77695f4d 272 //\r
b422b62c 273 FindAndReportModuleImageInfo (SIZE_4KB);\r
274 //\r
275 // Restore saved IDT entries\r
77695f4d 276 //\r
b422b62c 277 CopyMem ((VOID *)IdtDescriptor.Base, &IdtEntry, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR));\r
18b144ea 278\r
279 break;\r
280\r
281 case DEBUG_AGENT_INIT_ENTER_SMI:\r
282 SaveDebugRegister ();\r
6fee83fb
JF
283 if (!mSmmDebugIdtInitFlag) {\r
284 //\r
285 // We only need to initialize Debug IDT table at first SMI entry\r
286 // after SMM relocation.\r
287 //\r
288 InitializeDebugIdt ();\r
289 mSmmDebugIdtInitFlag = TRUE;\r
290 }\r
edbb2713
JF
291 //\r
292 // Check if CPU APIC Timer is working, otherwise initialize it.\r
293 //\r
df60fb4c 294 InitializeLocalApicSoftwareEnable (TRUE);\r
222c4930
LG
295 GetApicTimerState (&mApicTimerDivisor, &mPeriodicMode, &mVector);\r
296 mTimerCycle = GetApicTimerInitCount ();\r
297 if (!mPeriodicMode || mTimerCycle == 0) {\r
298 mApicTimerRestore = TRUE;\r
86d13652 299 InitializeDebugTimer (NULL, FALSE);\r
edbb2713 300 }\r
b422b62c 301 Mailbox = GetMailboxPointer ();\r
302 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {\r
18b144ea 303 //\r
b422b62c 304 // If Debug Agent has been communicaton state with HOST, we need skip\r
305 // any break points set in SMM, set Skip Breakpoint flag\r
18b144ea 306 //\r
b422b62c 307 mSkipBreakpoint = TRUE;\r
308 }\r
309 if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI) == 1) {\r
310 if (mSkipBreakpoint) {\r
311 //\r
312 // Print warning message if ignore smm entry break\r
313 //\r
314 DebugPortWriteBuffer ((DEBUG_PORT_HANDLE) (UINTN)Mailbox->DebugPortHandle,\r
315 (UINT8 *)mWarningMsgIgnoreSmmEntryBreak,\r
316 AsciiStrLen (mWarningMsgIgnoreSmmEntryBreak)\r
317 );\r
318 } else {\r
18b144ea 319 //\r
320 // If SMM entry break is set, SMM code will be break at here.\r
321 //\r
322 CpuBreakpoint ();\r
323 }\r
324 }\r
325 break;\r
326\r
327 case DEBUG_AGENT_INIT_EXIT_SMI:\r
b422b62c 328 Mailbox = GetMailboxPointer ();\r
329 //\r
330 // Clear Skip Breakpoint flag\r
331 //\r
332 mSkipBreakpoint = FALSE;\r
18b144ea 333 RestoreDebugRegister ();\r
222c4930
LG
334 //\r
335 // Restore APIC Timer\r
336 //\r
337 if (mApicTimerRestore) {\r
338 InitializeApicTimer (mApicTimerDivisor, mTimerCycle, mPeriodicMode, mVector);\r
339 mApicTimerRestore = FALSE;\r
340 }\r
18b144ea 341 break;\r
b422b62c 342\r
343 case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64:\r
344 if (Context == NULL) {\r
345 DEBUG ((EFI_D_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n"));\r
346 CpuDeadLoop ();\r
347 } else {\r
348 Ia32Idtr = (IA32_DESCRIPTOR *) Context;\r
349 Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);\r
3ee16809
HW
350 MailboxLocation = (UINT64 *) ((UINTN) Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow +\r
351 ((UINTN) Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));\r
b422b62c 352 mMailboxPointer = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
353 VerifyMailboxChecksum (mMailboxPointer);\r
354 //\r
355 // Get original IDT address and size.\r
356 //\r
357 AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
358 IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
359 if (IdtEntryCount < 33) {\r
360 Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);\r
361 Idtr.Base = (UINTN) &mIdtEntryTable;\r
362 ZeroMem (&mIdtEntryTable, Idtr.Limit + 1);\r
363 AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
364 }\r
365\r
366 InitializeDebugIdt ();\r
367 //\r
08021523 368 // Initialize Debug Timer hardware and save its frequency\r
b422b62c 369 //\r
86d13652 370 InitializeDebugTimer (&DebugTimerFrequency, TRUE);\r
08021523 371 UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);\r
2befbc82
JF
372 //\r
373 // Enable Debug Timer interrupt and CPU interrupt\r
374 //\r
375 SaveAndSetDebugTimerInterrupt (TRUE);\r
b422b62c 376 EnableInterrupts ();\r
377\r
378 FindAndReportModuleImageInfo (SIZE_4KB);\r
379 }\r
380 break;\r
381\r
382 default:\r
383 //\r
77695f4d 384 // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this\r
b422b62c 385 // Debug Agent library instance.\r
386 //\r
387 DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));\r
388 CpuDeadLoop ();\r
77695f4d 389 break;\r
18b144ea 390 }\r
391}\r
392\r