TianoCore EDK2 master
Loading...
Searching...
No Matches
SmmDebugAgentLib.c
Go to the documentation of this file.
1
9#include "SmmDebugAgentLib.h"
10
11DEBUG_AGENT_MAILBOX *mMailboxPointer = NULL;
12DEBUG_AGENT_MAILBOX mLocalMailbox;
13UINTN mSavedDebugRegisters[6];
14IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33];
15BOOLEAN mSkipBreakpoint = FALSE;
16BOOLEAN mSmmDebugIdtInitFlag = FALSE;
17BOOLEAN mApicTimerRestore = FALSE;
18BOOLEAN mPeriodicMode;
19UINT32 mTimerCycle;
20UINTN mApicTimerDivisor;
21UINT8 mVector;
22
23CHAR8 mWarningMsgIgnoreSmmEntryBreak[] = "Ignore smmentrybreak setting for SMI issued during DXE debugging!\r\n";
24
32BOOLEAN
34 VOID
35 )
36{
37 return FALSE;
38}
39
52 IN DEBUG_PORT_HANDLE Handle,
53 OUT UINT8 *BreakSymbol
54 )
55{
56 //
57 // Smm instance has no debug timer to poll break symbol.
58 //
59 return EFI_NOT_FOUND;
60}
61
70 VOID
71 )
72{
73 EFI_HOB_GUID_TYPE *GuidHob;
74 UINT64 *MailboxLocation;
75 DEBUG_AGENT_MAILBOX *Mailbox;
76
77 GuidHob = GetFirstGuidHob (&gEfiDebugAgentGuid);
78 if (GuidHob == NULL) {
79 return NULL;
80 }
81
82 MailboxLocation = (UINT64 *)(GET_GUID_HOB_DATA (GuidHob));
83 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
84 VerifyMailboxChecksum (Mailbox);
85
86 return Mailbox;
87}
88
97 VOID
98 )
99{
100 VerifyMailboxChecksum (mMailboxPointer);
101 return mMailboxPointer;
102}
103
110DEBUG_PORT_HANDLE
112 VOID
113 )
114{
115 return (DEBUG_PORT_HANDLE)(UINTN)(GetMailboxPointer ()->DebugPortHandle);
116}
117
122VOID
124 VOID
125 )
126{
127 mSavedDebugRegisters[0] = AsmReadDr0 ();
128 mSavedDebugRegisters[1] = AsmReadDr1 ();
129 mSavedDebugRegisters[2] = AsmReadDr2 ();
130 mSavedDebugRegisters[3] = AsmReadDr3 ();
131 mSavedDebugRegisters[4] = AsmReadDr6 ();
132 mSavedDebugRegisters[5] = AsmReadDr7 ();
133}
134
139VOID
141 VOID
142 )
143{
144 AsmWriteDr7 (0);
145 AsmWriteDr0 (mSavedDebugRegisters[0]);
146 AsmWriteDr1 (mSavedDebugRegisters[1]);
147 AsmWriteDr2 (mSavedDebugRegisters[2]);
148 AsmWriteDr3 (mSavedDebugRegisters[3]);
149 AsmWriteDr6 (mSavedDebugRegisters[4]);
150 AsmWriteDr7 (mSavedDebugRegisters[5]);
151}
152
176VOID
177EFIAPI
179 IN UINT32 InitFlag,
180 IN VOID *Context OPTIONAL,
181 IN DEBUG_AGENT_CONTINUE Function OPTIONAL
182 )
183{
184 EFI_STATUS Status;
185 UINT64 DebugPortHandle;
186 IA32_IDT_GATE_DESCRIPTOR IdtEntry[33];
187 IA32_DESCRIPTOR IdtDescriptor;
188 IA32_DESCRIPTOR *Ia32Idtr;
189 IA32_IDT_ENTRY *Ia32IdtEntry;
190 IA32_DESCRIPTOR Idtr;
191 UINT16 IdtEntryCount;
192 DEBUG_AGENT_MAILBOX *Mailbox;
193 UINT64 *MailboxLocation;
194 UINT32 DebugTimerFrequency;
195
196 switch (InitFlag) {
197 case DEBUG_AGENT_INIT_SMM:
198 //
199 // Install configuration table for persisted vector handoff info
200 //
201 Status = gSmst->SmmInstallConfigurationTable (
202 gSmst,
203 &gEfiVectorHandoffTableGuid,
204 (VOID *)&mVectorHandoffInfoDebugAgent[0],
205 sizeof (EFI_VECTOR_HANDOFF_INFO) * mVectorHandoffInfoCount
206 );
207 if (EFI_ERROR (Status)) {
208 DEBUG ((DEBUG_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n"));
209 if (Context != NULL) {
210 *(BOOLEAN *)Context = FALSE;
211 }
212
213 CpuDeadLoop ();
214 }
215
216 //
217 // Check if Debug Agent initialized in DXE phase
218 //
219 Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **)&Mailbox);
220 if ((Status == EFI_SUCCESS) && (Mailbox != NULL)) {
221 VerifyMailboxChecksum (Mailbox);
222 mMailboxPointer = Mailbox;
223 if (Context != NULL) {
224 *(BOOLEAN *)Context = TRUE;
225 }
226
227 break;
228 }
229
230 //
231 // Check if Debug Agent initialized in SEC/PEI phase
232 //
233 Mailbox = GetMailboxFromHob ();
234 if (Mailbox != NULL) {
235 mMailboxPointer = Mailbox;
236 if (Context != NULL) {
237 *(BOOLEAN *)Context = TRUE;
238 }
239
240 break;
241 }
242
243 //
244 // Debug Agent was not initialized before, use the local mailbox.
245 //
246 ZeroMem (&mLocalMailbox, sizeof (DEBUG_AGENT_MAILBOX));
247 Mailbox = &mLocalMailbox;
248 //
249 // Save original IDT entries
250 //
251 AsmReadIdtr (&IdtDescriptor);
252 CopyMem (&IdtEntry, (VOID *)IdtDescriptor.Base, 33 * sizeof (IA32_IDT_GATE_DESCRIPTOR));
253 //
254 // Initialized Debug Agent
255 //
257 //
258 // Initialize Debug Timer hardware and save its frequency
259 //
260 InitializeDebugTimer (&DebugTimerFrequency, TRUE);
261 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
262
263 DebugPortHandle = (UINT64)(UINTN)DebugPortInitialize ((DEBUG_PORT_HANDLE)(UINTN)Mailbox->DebugPortHandle, NULL);
264 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);
265 mMailboxPointer = Mailbox;
266 //
267 // Trigger one software interrupt to inform HOST
268 //
269 TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);
270
271 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);
272 //
273 // Memory has been ready
274 //
275 if (IsHostAttached ()) {
276 //
277 // Trigger one software interrupt to inform HOST
278 //
279 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
280 }
281
282 //
283 // Find and report PE/COFF image info to HOST
284 //
286 //
287 // Restore saved IDT entries
288 //
289 CopyMem ((VOID *)IdtDescriptor.Base, &IdtEntry, 33 * sizeof (IA32_IDT_GATE_DESCRIPTOR));
290
291 if (Context != NULL) {
292 *(BOOLEAN *)Context = TRUE;
293 }
294
295 break;
296
297 case DEBUG_AGENT_INIT_ENTER_SMI:
299 if (!mSmmDebugIdtInitFlag) {
300 //
301 // We only need to initialize Debug IDT table at first SMI entry
302 // after SMM relocation.
303 //
305 mSmmDebugIdtInitFlag = TRUE;
306 }
307
308 //
309 // Check if CPU APIC Timer is working, otherwise initialize it.
310 //
312 GetApicTimerState (&mApicTimerDivisor, &mPeriodicMode, &mVector);
313 mTimerCycle = GetApicTimerInitCount ();
314 if (!mPeriodicMode || (mTimerCycle == 0)) {
315 mApicTimerRestore = TRUE;
317 }
318
319 Mailbox = GetMailboxPointer ();
320 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS) == 1) {
321 //
322 // If Debug Agent has been communication state with HOST, we need skip
323 // any break points set in SMM, set Skip Breakpoint flag
324 //
325 mSkipBreakpoint = TRUE;
326 }
327
328 if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI) == 1) {
329 if (mSkipBreakpoint) {
330 //
331 // Print warning message if ignore smm entry break
332 //
334 (DEBUG_PORT_HANDLE)(UINTN)Mailbox->DebugPortHandle,
335 (UINT8 *)mWarningMsgIgnoreSmmEntryBreak,
336 AsciiStrLen (mWarningMsgIgnoreSmmEntryBreak)
337 );
338 } else {
339 //
340 // If SMM entry break is set, SMM code will be break at here.
341 //
342 CpuBreakpoint ();
343 }
344 }
345
346 break;
347
348 case DEBUG_AGENT_INIT_EXIT_SMI:
349 Mailbox = GetMailboxPointer ();
350 //
351 // Clear Skip Breakpoint flag
352 //
353 mSkipBreakpoint = FALSE;
355 //
356 // Restore APIC Timer
357 //
358 if (mApicTimerRestore) {
359 InitializeApicTimer (mApicTimerDivisor, mTimerCycle, mPeriodicMode, mVector);
360 mApicTimerRestore = FALSE;
361 }
362
363 break;
364
365 case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64:
366 if (Context == NULL) {
367 DEBUG ((DEBUG_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n"));
368 CpuDeadLoop ();
369 } else {
370 Ia32Idtr = (IA32_DESCRIPTOR *)Context;
371 Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);
372 MailboxLocation = (UINT64 *)((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow +
373 ((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));
374 mMailboxPointer = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
375 VerifyMailboxChecksum (mMailboxPointer);
376 //
377 // Get original IDT address and size.
378 //
379 AsmReadIdtr ((IA32_DESCRIPTOR *)&Idtr);
380 IdtEntryCount = (UINT16)((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
381 if (IdtEntryCount < 33) {
382 Idtr.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
383 Idtr.Base = (UINTN)&mIdtEntryTable;
384 ZeroMem (&mIdtEntryTable, Idtr.Limit + 1);
385 AsmWriteIdtr ((IA32_DESCRIPTOR *)&Idtr);
386 }
387
389 //
390 // Initialize Debug Timer hardware and save its frequency
391 //
392 InitializeDebugTimer (&DebugTimerFrequency, TRUE);
393 UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
394 //
395 // Enable Debug Timer interrupt and CPU interrupt
396 //
399
401 }
402
403 break;
404
405 default:
406 //
407 // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this
408 // Debug Agent library instance.
409 //
410 DEBUG ((DEBUG_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));
411 CpuDeadLoop ();
412 break;
413 }
414}
UINT64 UINTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
VOID EFIAPI EnableInterrupts(VOID)
Definition: CpuBreakpoint.c:67
VOID EFIAPI CpuBreakpoint(VOID)
Definition: CpuBreakpoint.c:26
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID UpdateMailboxContent(IN DEBUG_AGENT_MAILBOX *Mailbox, IN UINTN Index, IN UINT64 Value)
Definition: DebugAgent.c:300
UINT32 GetDebugFlag(IN UINT64 FlagMask)
Definition: DebugAgent.c:458
BOOLEAN IsHostAttached(VOID)
Definition: DebugAgent.c:676
VOID VerifyMailboxChecksum(IN DEBUG_AGENT_MAILBOX *Mailbox)
Definition: DebugAgent.c:273
VOID SetDebugFlag(IN UINT64 FlagMask, IN UINT32 FlagValue)
Definition: DebugAgent.c:435
VOID FindAndReportModuleImageInfo(IN UINTN AlignSize)
Definition: DebugAgent.c:193
VOID TriggerSoftInterrupt(IN UINT32 Signature)
Definition: DebugAgent.c:218
VOID InitializeDebugIdt(VOID)
VOID(EFIAPI * DEBUG_AGENT_CONTINUE)(IN VOID *Context)
Definition: DebugAgentLib.h:43
BOOLEAN EFIAPI SaveAndSetDebugTimerInterrupt(IN BOOLEAN EnableStatus)
DEBUG_PORT_HANDLE EFIAPI DebugPortInitialize(IN VOID *Context, IN DEBUG_PORT_CONTINUE Function)
UINTN EFIAPI DebugPortWriteBuffer(IN DEBUG_PORT_HANDLE Handle, IN UINT8 *Buffer, IN UINTN NumberOfBytes)
UINT32 InitializeDebugTimer(OUT UINT32 *TimerFrequency, IN BOOLEAN DumpFlag)
Definition: DebugTimer.c:20
UINTN EFIAPI AsmWriteDr1(UINTN Dr1)
UINTN EFIAPI AsmReadDr1(VOID)
UINTN EFIAPI AsmReadDr0(VOID)
UINTN EFIAPI AsmWriteDr7(UINTN Dr7)
UINTN EFIAPI AsmWriteDr3(UINTN Dr3)
UINTN EFIAPI AsmReadDr2(VOID)
UINTN EFIAPI AsmWriteDr2(UINTN Dr2)
UINTN EFIAPI AsmWriteDr0(UINTN Dr0)
UINTN EFIAPI AsmReadDr3(VOID)
UINTN EFIAPI AsmReadDr6(VOID)
UINTN EFIAPI AsmWriteDr6(UINTN Dr6)
UINTN EFIAPI AsmReadDr7(VOID)
VOID EFIAPI InitializeLocalApicSoftwareEnable(IN BOOLEAN Enable)
Definition: BaseXApicLib.c:600
VOID EFIAPI GetApicTimerState(OUT UINTN *DivideValue OPTIONAL, OUT BOOLEAN *PeriodicMode OPTIONAL, OUT UINT8 *Vector OPTIONAL)
Definition: BaseXApicLib.c:790
UINT32 EFIAPI GetApicTimerInitCount(VOID)
Definition: BaseXApicLib.c:698
VOID EFIAPI InitializeApicTimer(IN UINTN DivideValue, IN UINT32 InitCount, IN BOOLEAN PeriodicMode, IN UINT8 Vector)
Definition: BaseXApicLib.c:732
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
EFI_SMM_SYSTEM_TABLE2 * gSmst
VOID SaveDebugRegister(VOID)
DEBUG_AGENT_MAILBOX * GetMailboxFromHob(VOID)
DEBUG_AGENT_MAILBOX * GetMailboxPointer(VOID)
BOOLEAN MultiProcessorDebugSupport(VOID)
VOID RestoreDebugRegister(VOID)
VOID EFIAPI InitializeDebugAgent(IN UINT32 InitFlag, IN VOID *Context OPTIONAL, IN DEBUG_AGENT_CONTINUE Function OPTIONAL)
DEBUG_PORT_HANDLE GetDebugPortHandle(VOID)
EFI_STATUS DebugReadBreakSymbol(IN DEBUG_PORT_HANDLE Handle, OUT UINT8 *BreakSymbol)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82
VOID EFIAPI AsmReadIdtr(OUT IA32_DESCRIPTOR *Idtr)
Definition: X86ReadIdtr.c:24
VOID EFIAPI AsmWriteIdtr(IN CONST IA32_DESCRIPTOR *Idtr)
UINT32 OffsetLow
Offset bits 15..0.
Definition: DebugAgent.h:150