TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeDebugAgentLib.c
Go to the documentation of this file.
1
9#include "DxeDebugAgentLib.h"
10
11DEBUG_AGENT_MAILBOX mMailbox;
12DEBUG_AGENT_MAILBOX *mMailboxPointer = NULL;
13IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33];
14BOOLEAN mDxeCoreFlag = FALSE;
15BOOLEAN mMultiProcessorDebugSupport = FALSE;
16VOID *mSavedIdtTable = NULL;
17UINTN mSaveIdtTableSize = 0;
18BOOLEAN mDebugAgentInitialized = FALSE;
19BOOLEAN mSkipBreakpoint = FALSE;
20
28BOOLEAN
30 VOID
31 )
32{
33 return mMultiProcessorDebugSupport;
34}
35
44VOID
46 VOID
47 )
48{
49 EFI_STATUS Status;
51 BOOLEAN DebugTimerInterruptState;
52 DEBUG_AGENT_MAILBOX *Mailbox;
53 DEBUG_AGENT_MAILBOX *NewMailbox;
54 EFI_HOB_GUID_TYPE *GuidHob;
55 EFI_VECTOR_HANDOFF_INFO *VectorHandoffInfo;
56
57 //
58 // Check persisted vector handoff info
59 //
60 Status = EFI_SUCCESS;
61 GuidHob = GetFirstGuidHob (&gEfiVectorHandoffInfoPpiGuid);
62 if ((GuidHob != NULL) && !mDxeCoreFlag) {
63 //
64 // Check if configuration table is installed or not if GUIDed HOB existed,
65 // only when Debug Agent is not linked by DXE Core
66 //
67 Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **)&VectorHandoffInfo);
68 }
69
70 if ((GuidHob == NULL) || (Status != EFI_SUCCESS)) {
71 //
72 // Install configuration table for persisted vector handoff info if GUIDed HOB cannot be found or
73 // configuration table does not exist
74 //
75 Status = gBS->InstallConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID *)&mVectorHandoffInfoDebugAgent[0]);
76 if (EFI_ERROR (Status)) {
77 DEBUG ((DEBUG_ERROR, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n"));
78 CpuDeadLoop ();
79 }
80 }
81
82 //
83 // Install EFI Serial IO protocol on debug port
84 //
86
87 Address = 0;
88 Status = gBS->AllocatePages (
91 EFI_SIZE_TO_PAGES (sizeof (DEBUG_AGENT_MAILBOX) + PcdGet16 (PcdDebugPortHandleBufferSize)),
92 &Address
93 );
94 if (EFI_ERROR (Status)) {
95 DEBUG ((DEBUG_ERROR, "DebugAgent: Cannot install configuration table for mailbox!\n"));
96 CpuDeadLoop ();
97 }
98
99 DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
100
101 NewMailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)Address;
102 //
103 // Copy Mailbox and Debug Port Handle buffer to new location in ACPI NVS memory, because original Mailbox
104 // and Debug Port Handle buffer may be free at runtime, SMM debug agent needs to access them
105 //
106 Mailbox = GetMailboxPointer ();
107 CopyMem (NewMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
108 CopyMem (NewMailbox + 1, (VOID *)(UINTN)Mailbox->DebugPortHandle, PcdGet16 (PcdDebugPortHandleBufferSize));
109 //
110 // Update Debug Port Handle in new Mailbox
111 //
112 UpdateMailboxContent (NewMailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, (UINT64)(UINTN)(NewMailbox + 1));
113 mMailboxPointer = NewMailbox;
114
115 DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
116
117 Status = gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *)mMailboxPointer);
118 if (EFI_ERROR (Status)) {
119 DEBUG ((DEBUG_ERROR, "DebugAgent: Failed to install configuration for mailbox!\n"));
120 CpuDeadLoop ();
121 }
122}
123
133RETURN_STATUS
134EFIAPI
136 IN EFI_HANDLE ImageHandle,
137 IN EFI_SYSTEM_TABLE *SystemTable
138 )
139{
140 if (mDxeCoreFlag) {
141 //
142 // Invoke internal constructor function only when DXE core links this library instance
143 //
145 }
146
147 return RETURN_SUCCESS;
148}
149
158 VOID
159 )
160{
161 EFI_STATUS Status;
162 DEBUG_AGENT_MAILBOX *Mailbox;
163
164 Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **)&Mailbox);
165 if ((Status == EFI_SUCCESS) && (Mailbox != NULL)) {
166 VerifyMailboxChecksum (Mailbox);
167 return Mailbox;
168 } else {
169 return NULL;
170 }
171}
172
183 IN VOID *HobStart
184 )
185{
186 EFI_HOB_GUID_TYPE *GuidHob;
187 UINT64 *MailboxLocation;
188 DEBUG_AGENT_MAILBOX *Mailbox;
189
190 GuidHob = GetNextGuidHob (&gEfiDebugAgentGuid, HobStart);
191 if (GuidHob == NULL) {
192 return NULL;
193 }
194
195 MailboxLocation = (UINT64 *)(GET_GUID_HOB_DATA (GuidHob));
196 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
197 VerifyMailboxChecksum (Mailbox);
198
199 return Mailbox;
200}
201
210 VOID
211 )
212{
213 AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock);
214 VerifyMailboxChecksum (mMailboxPointer);
215 ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);
216 return mMailboxPointer;
217}
218
225DEBUG_PORT_HANDLE
227 VOID
228 )
229{
230 return (DEBUG_PORT_HANDLE)(UINTN)(GetMailboxPointer ()->DebugPortHandle);
231}
232
243VOID
245 IN DEBUG_AGENT_MAILBOX *Mailbox
246 )
247{
248 IA32_DESCRIPTOR Idtr;
249 UINT16 IdtEntryCount;
250 UINT64 DebugPortHandle;
251 UINT32 DebugTimerFrequency;
252
253 if (mMultiProcessorDebugSupport) {
254 InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);
255 InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);
256 InitializeSpinLock (&mDebugMpContext.MailboxSpinLock);
257 //
258 // Clear Break CPU index value
259 //
260 mDebugMpContext.BreakAtCpuIndex = (UINT32)-1;
261 }
262
263 //
264 // Get original IDT address and size.
265 //
266 AsmReadIdtr ((IA32_DESCRIPTOR *)&Idtr);
267 IdtEntryCount = (UINT16)((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
268 if (IdtEntryCount < 33) {
269 ZeroMem (&mIdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33);
270 //
271 // Copy original IDT table into new one
272 //
273 CopyMem (&mIdtEntryTable, (VOID *)Idtr.Base, Idtr.Limit + 1);
274 //
275 // Load new IDT table
276 //
277 Idtr.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
278 Idtr.Base = (UINTN)&mIdtEntryTable;
279 AsmWriteIdtr ((IA32_DESCRIPTOR *)&Idtr);
280 }
281
282 //
283 // Initialize the IDT table entries to support source level debug.
284 //
286
287 //
288 // If mMailboxPointer is not set before, set it
289 //
290 if (mMailboxPointer == NULL) {
291 if (Mailbox != NULL) {
292 //
293 // If Mailbox exists, copy it into one global variable
294 //
295 CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
296 } else {
297 ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));
298 }
299
300 mMailboxPointer = &mMailbox;
301 }
302
303 //
304 // Initialize Debug Timer hardware and save its initial count and frequency
305 //
306 mDebugMpContext.DebugTimerInitCount = InitializeDebugTimer (&DebugTimerFrequency, TRUE);
307 UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency);
308 //
309 // Initialize debug communication port
310 //
311 DebugPortHandle = (UINT64)(UINTN)DebugPortInitialize ((VOID *)(UINTN)mMailboxPointer->DebugPortHandle, NULL);
312 UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);
313
314 if (Mailbox == NULL) {
315 //
316 // Trigger one software interrupt to inform HOST
317 //
318 TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);
319 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);
320 //
321 // Memory has been ready
322 //
323 if (IsHostAttached ()) {
324 //
325 // Trigger one software interrupt to inform HOST
326 //
327 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
328 }
329 }
330}
331
349VOID
350EFIAPI
352 IN UINT32 InitFlag,
353 IN VOID *Context OPTIONAL,
354 IN DEBUG_AGENT_CONTINUE Function OPTIONAL
355 )
356{
357 UINT64 *MailboxLocation;
358 DEBUG_AGENT_MAILBOX *Mailbox;
359 BOOLEAN InterruptStatus;
360 VOID *HobList;
361 IA32_DESCRIPTOR IdtDescriptor;
362 IA32_DESCRIPTOR *Ia32Idtr;
363 IA32_IDT_ENTRY *Ia32IdtEntry;
364 BOOLEAN PeriodicMode;
365 UINTN TimerCycle;
366
367 if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {
368 //
369 // Check if CPU APIC Timer is working, otherwise initialize it.
370 //
372 GetApicTimerState (NULL, &PeriodicMode, NULL);
373 TimerCycle = GetApicTimerInitCount ();
374 if (!PeriodicMode || (TimerCycle == 0)) {
376 }
377
378 //
379 // Invoked by AP, enable interrupt to let AP could receive IPI from other processors
380 //
382 return;
383 }
384
385 //
386 // Disable Debug Timer interrupt
387 //
389 //
390 // Save and disable original interrupt status
391 //
392 InterruptStatus = SaveAndDisableInterrupts ();
393
394 //
395 // Try to get mailbox firstly
396 //
397 HobList = NULL;
398 Mailbox = NULL;
399 MailboxLocation = NULL;
400
401 switch (InitFlag) {
402 case DEBUG_AGENT_INIT_DXE_LOAD:
403 //
404 // Check if Debug Agent has been initialized before
405 //
406 if (IsDebugAgentInitialzed ()) {
407 DEBUG ((DEBUG_INFO, "Debug Agent: The former agent will be overwritten by the new one!\n"));
408 }
409
410 mMultiProcessorDebugSupport = TRUE;
411 //
412 // Save original IDT table
413 //
414 AsmReadIdtr (&IdtDescriptor);
415 mSaveIdtTableSize = IdtDescriptor.Limit + 1;
416 mSavedIdtTable = AllocateCopyPool (mSaveIdtTableSize, (VOID *)IdtDescriptor.Base);
417 //
418 // Check if Debug Agent initialized in DXE phase
419 //
421 if (Mailbox == NULL) {
422 //
423 // Try to get mailbox from GUIDed HOB build in PEI
424 //
425 HobList = GetHobList ();
426 Mailbox = GetMailboxFromHob (HobList);
427 }
428
429 //
430 // Set up Debug Agent Environment and try to connect HOST if required
431 //
433 //
434 // For DEBUG_AGENT_INIT_S3, needn't to install configuration table and EFI Serial IO protocol
435 // For DEBUG_AGENT_INIT_DXE_CORE, InternalConstructorWorker() will invoked in Constructor()
436 //
438 //
439 // Enable Debug Timer interrupt
440 //
442 //
443 // Enable interrupt to receive Debug Timer interrupt
444 //
446
447 mDebugAgentInitialized = TRUE;
449
450 *(EFI_STATUS *)Context = EFI_SUCCESS;
451
452 break;
453
454 case DEBUG_AGENT_INIT_DXE_UNLOAD:
455 if (mDebugAgentInitialized) {
456 if (IsHostAttached ()) {
457 *(EFI_STATUS *)Context = EFI_ACCESS_DENIED;
458 //
459 // Enable Debug Timer interrupt again
460 //
462 } else {
463 //
464 // Restore original IDT table
465 //
466 AsmReadIdtr (&IdtDescriptor);
467 IdtDescriptor.Limit = (UINT16)(mSaveIdtTableSize - 1);
468 CopyMem ((VOID *)IdtDescriptor.Base, mSavedIdtTable, mSaveIdtTableSize);
469 AsmWriteIdtr (&IdtDescriptor);
470 FreePool (mSavedIdtTable);
471 mDebugAgentInitialized = FALSE;
472 *(EFI_STATUS *)Context = EFI_SUCCESS;
473 }
474 } else {
475 *(EFI_STATUS *)Context = EFI_NOT_STARTED;
476 }
477
478 //
479 // Restore interrupt state.
480 //
481 SetInterruptState (InterruptStatus);
482 break;
483
484 case DEBUG_AGENT_INIT_DXE_CORE:
485 mDxeCoreFlag = TRUE;
486 mMultiProcessorDebugSupport = TRUE;
487 //
488 // Try to get mailbox from GUIDed HOB build in PEI
489 //
490 HobList = Context;
491 Mailbox = GetMailboxFromHob (HobList);
492 //
493 // Set up Debug Agent Environment and try to connect HOST if required
494 //
496 //
497 // Enable Debug Timer interrupt
498 //
500 //
501 // Enable interrupt to receive Debug Timer interrupt
502 //
504
505 break;
506
507 case DEBUG_AGENT_INIT_S3:
508
509 if (Context != NULL) {
510 Ia32Idtr = (IA32_DESCRIPTOR *)Context;
511 Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);
512 MailboxLocation = (UINT64 *)((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow +
513 ((UINTN)Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));
514 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);
515 VerifyMailboxChecksum (Mailbox);
516 }
517
518 //
519 // Save Mailbox pointer in global variable
520 //
521 mMailboxPointer = Mailbox;
522 //
523 // Set up Debug Agent Environment and try to connect HOST if required
524 //
526 //
527 // Disable interrupt
528 //
531 if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT) == 1) {
532 //
533 // If Boot Script entry break is set, code will be break at here.
534 //
535 CpuBreakpoint ();
536 }
537
538 break;
539
540 default:
541 //
542 // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this
543 // Debug Agent library instance.
544 //
545 DEBUG ((DEBUG_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));
546 CpuDeadLoop ();
547 break;
548 }
549}
UINT64 UINTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
VOID *EFIAPI GetNextGuidHob(IN CONST EFI_GUID *Guid, IN CONST VOID *HobStart)
Definition: HobLib.c:176
VOID *EFIAPI GetHobList(VOID)
Definition: HobLib.c:76
BOOLEAN EFIAPI SetInterruptState(IN BOOLEAN InterruptState)
Definition: Cpu.c:48
BOOLEAN EFIAPI SaveAndDisableInterrupts(VOID)
Definition: Cpu.c:21
VOID EFIAPI CpuDeadLoop(VOID)
Definition: CpuDeadLoop.c:25
VOID EFIAPI EnableInterrupts(VOID)
Definition: CpuBreakpoint.c:67
VOID EFIAPI DisableInterrupts(VOID)
Definition: CpuBreakpoint.c:54
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
BOOLEAN IsDebugAgentInitialzed(VOID)
Definition: DebugAgent.c:172
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)
VOID ReleaseMpSpinLock(IN OUT SPIN_LOCK *MpSpinLock)
Definition: DebugMp.c:50
VOID AcquireMpSpinLock(IN OUT SPIN_LOCK *MpSpinLock)
Definition: DebugMp.c:25
UINT32 InitializeDebugTimer(OUT UINT32 *TimerFrequency, IN BOOLEAN DumpFlag)
Definition: DebugTimer.c:20
VOID SetupDebugAgentEnvironment(IN DEBUG_AGENT_MAILBOX *Mailbox)
DEBUG_AGENT_MAILBOX * GetMailboxFromHob(IN VOID *HobStart)
DEBUG_AGENT_MAILBOX * GetMailboxPointer(VOID)
BOOLEAN MultiProcessorDebugSupport(VOID)
VOID InternalConstructorWorker(VOID)
RETURN_STATUS EFIAPI DxeDebugAgentLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
VOID EFIAPI InitializeDebugAgent(IN UINT32 InitFlag, IN VOID *Context OPTIONAL, IN DEBUG_AGENT_CONTINUE Function OPTIONAL)
DEBUG_PORT_HANDLE GetDebugPortHandle(VOID)
DEBUG_AGENT_MAILBOX * GetMailboxFromConfigurationTable(VOID)
VOID InstallSerialIo(VOID)
Definition: SerialIo.c:364
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
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
#define NULL
Definition: Base.h:319
#define RETURN_SUCCESS
Definition: Base.h:1066
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet16(TokenName)
Definition: PcdLib.h:349
SPIN_LOCK *EFIAPI InitializeSpinLock(OUT SPIN_LOCK *SpinLock)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82
@ EfiACPIMemoryNVS
@ AllocateAnyPages
Definition: UefiSpec.h:33
VOID EFIAPI AsmReadIdtr(OUT IA32_DESCRIPTOR *Idtr)
Definition: X86ReadIdtr.c:24
VOID EFIAPI AsmWriteIdtr(IN CONST IA32_DESCRIPTOR *Idtr)
SPIN_LOCK MpContextSpinLock
Lock for writing MP context.
Definition: DebugMp.h:20
SPIN_LOCK MailboxSpinLock
Lock for accessing mail box.
Definition: DebugMp.h:22
UINT32 DebugTimerInitCount
Record BSP's init timer count.
Definition: DebugMp.h:28
SPIN_LOCK DebugPortSpinLock
Lock for access debug port.
Definition: DebugMp.h:21
UINT32 BreakAtCpuIndex
Processor index value of the current breaking CPU.
Definition: DebugMp.h:27
UINT32 OffsetLow
Offset bits 15..0.
Definition: DebugAgent.h:150