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