2 Debug Agent library implementition.
4 Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
5 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.
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.
15 #include "SmmDebugAgentLib.h"
17 DEBUG_AGENT_MAILBOX
*mMailboxPointer
= NULL
;
18 DEBUG_AGENT_MAILBOX mLocalMailbox
;
19 UINTN mSavedDebugRegisters
[6];
20 IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable
[33];
21 BOOLEAN mSkipBreakpoint
= FALSE
;
23 CHAR8 mWarningMsgIgnoreSmmEntryBreak
[] = "Ignore smmentrybreak setting for SMI issued during DXE debugging!\r\n";
26 Check if debug agent support multi-processor.
28 @retval TRUE Multi-processor is supported.
29 @retval FALSE Multi-processor is not supported.
33 MultiProcessorDebugSupport (
41 Read the Attach/Break-in symbols from the debug port.
43 @param[in] Handle Pointer to Debug Port handle.
44 @param[out] BreakSymbol Returned break symbol.
46 @retval EFI_SUCCESS Read the symbol in BreakSymbol.
47 @retval EFI_NOT_FOUND No read the break symbol.
51 DebugReadBreakSymbol (
52 IN DEBUG_PORT_HANDLE Handle
,
53 OUT UINT8
*BreakSymbol
57 // Smm instance has no debug timer to poll break symbol.
63 Get the pointer to Mailbox from the GUIDed HOB.
65 @return Pointer to Mailbox.
73 EFI_HOB_GUID_TYPE
*GuidHob
;
74 UINT64
*MailboxLocation
;
75 DEBUG_AGENT_MAILBOX
*Mailbox
;
77 GuidHob
= GetFirstGuidHob (&gEfiDebugAgentGuid
);
78 if (GuidHob
== NULL
) {
81 MailboxLocation
= (UINT64
*) (GET_GUID_HOB_DATA(GuidHob
));
82 Mailbox
= (DEBUG_AGENT_MAILBOX
*)(UINTN
)(*MailboxLocation
);
83 VerifyMailboxChecksum (Mailbox
);
89 Get Debug Agent Mailbox pointer.
91 @return Mailbox pointer.
99 VerifyMailboxChecksum (mMailboxPointer
);
100 return mMailboxPointer
;
104 Get debug port handle.
106 @return Debug port handle.
114 return (DEBUG_PORT_HANDLE
) (UINTN
)(GetMailboxPointer()->DebugPortHandle
);
118 Store debug register when SMI exit.
126 mSavedDebugRegisters
[0] = AsmReadDr0 ();
127 mSavedDebugRegisters
[1] = AsmReadDr1 ();
128 mSavedDebugRegisters
[2] = AsmReadDr2 ();
129 mSavedDebugRegisters
[3] = AsmReadDr3 ();
130 mSavedDebugRegisters
[4] = AsmReadDr6 ();
131 mSavedDebugRegisters
[5] = AsmReadDr7 ();
135 Restore debug register when SMI exit.
139 RestoreDebugRegister (
144 AsmWriteDr0 (mSavedDebugRegisters
[0]);
145 AsmWriteDr1 (mSavedDebugRegisters
[1]);
146 AsmWriteDr2 (mSavedDebugRegisters
[2]);
147 AsmWriteDr3 (mSavedDebugRegisters
[3]);
148 AsmWriteDr6 (mSavedDebugRegisters
[4]);
149 AsmWriteDr7 (mSavedDebugRegisters
[5]);
153 Initialize debug agent.
155 This function is used to set up debug enviroment for source level debug
158 If InitFlag is DEBUG_AGENT_INIT_SMM, it will overirde IDT table entries
159 and initialize debug port. It will get debug agent Mailbox from GUIDed HOB,
160 it it exists, debug agent wiil copied it into the local Mailbox in SMM space.
161 it will overirde IDT table entries and initialize debug port. Context will be
163 If InitFlag is DEBUG_AGENT_INIT_ENTER_SMI, debug agent will save Debug
164 Registers and get local Mailbox in SMM space. Context will be NULL.
165 If InitFlag is DEBUG_AGENT_INIT_EXIT_SMI, debug agent will restore Debug
166 Registers. Context will be NULL.
168 @param[in] InitFlag Init flag is used to decide initialize process.
169 @param[in] Context Context needed according to InitFlag.
170 @param[in] Function Continue function called by debug agent library; it was
176 InitializeDebugAgent (
178 IN VOID
*Context
, OPTIONAL
179 IN DEBUG_AGENT_CONTINUE Function OPTIONAL
183 UINT64 DebugPortHandle
;
184 IA32_IDT_GATE_DESCRIPTOR IdtEntry
[33];
185 IA32_DESCRIPTOR IdtDescriptor
;
186 IA32_DESCRIPTOR
*Ia32Idtr
;
187 IA32_IDT_ENTRY
*Ia32IdtEntry
;
188 IA32_DESCRIPTOR Idtr
;
189 UINT16 IdtEntryCount
;
190 DEBUG_AGENT_MAILBOX
*Mailbox
;
191 UINT64
*MailboxLocation
;
192 UINT32 DebugTimerFrequency
;
195 case DEBUG_AGENT_INIT_SMM
:
197 // Install configuration table for persisted vector handoff info
199 Status
= gSmst
->SmmInstallConfigurationTable (
201 &gEfiVectorHandoffTableGuid
,
202 (VOID
*) &mVectorHandoffInfoDebugAgent
[0],
203 sizeof (EFI_VECTOR_HANDOFF_INFO
) * mVectorHandoffInfoCount
205 if (EFI_ERROR (Status
)) {
206 DEBUG ((EFI_D_ERROR
, "DebugAgent: Cannot install configuration table for persisted vector handoff info!\n"));
210 // Check if Debug Agent initialized in DXE phase
212 Status
= EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid
, (VOID
**) &Mailbox
);
213 if (Status
== EFI_SUCCESS
&& Mailbox
!= NULL
) {
214 VerifyMailboxChecksum (Mailbox
);
215 mMailboxPointer
= Mailbox
;
219 // Check if Debug Agent initialized in SEC/PEI phase
221 Mailbox
= GetMailboxFromHob ();
222 if (Mailbox
!= NULL
) {
223 mMailboxPointer
= Mailbox
;
227 // Debug Agent was not initialized before, use the local mailbox.
229 ZeroMem (&mLocalMailbox
, sizeof (DEBUG_AGENT_MAILBOX
));
230 Mailbox
= &mLocalMailbox
;
232 // Save original IDT entries
234 AsmReadIdtr (&IdtDescriptor
);
235 CopyMem (&IdtEntry
, (VOID
*)IdtDescriptor
.Base
, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR
));
237 // Initialized Debug Agent
239 InitializeDebugIdt ();
241 // Initialize Debug Timer hardware and save its frequency
243 InitializeDebugTimer (&DebugTimerFrequency
);
244 UpdateMailboxContent (mMailboxPointer
, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY
, DebugTimerFrequency
);
246 DebugPortHandle
= (UINT64
) (UINTN
)DebugPortInitialize ((DEBUG_PORT_HANDLE
) (UINTN
)Mailbox
->DebugPortHandle
, NULL
);
247 UpdateMailboxContent (Mailbox
, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX
, DebugPortHandle
);
248 mMailboxPointer
= Mailbox
;
250 // Trigger one software interrupt to inform HOST
252 TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE
);
254 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY
, 1);
256 // Memory has been ready
258 if (IsHostAttached ()) {
260 // Trigger one software interrupt to inform HOST
262 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE
);
265 // Find and report PE/COFF image info to HOST
267 FindAndReportModuleImageInfo (SIZE_4KB
);
269 // Restore saved IDT entries
271 CopyMem ((VOID
*)IdtDescriptor
.Base
, &IdtEntry
, 33 * sizeof(IA32_IDT_GATE_DESCRIPTOR
));
275 case DEBUG_AGENT_INIT_ENTER_SMI
:
276 SaveDebugRegister ();
277 InitializeDebugIdt ();
279 Mailbox
= GetMailboxPointer ();
280 if (GetDebugFlag (DEBUG_AGENT_FLAG_AGENT_IN_PROGRESS
) == 1) {
282 // If Debug Agent has been communicaton state with HOST, we need skip
283 // any break points set in SMM, set Skip Breakpoint flag
285 mSkipBreakpoint
= TRUE
;
287 if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_ON_NEXT_SMI
) == 1) {
288 if (mSkipBreakpoint
) {
290 // Print warning message if ignore smm entry break
292 DebugPortWriteBuffer ((DEBUG_PORT_HANDLE
) (UINTN
)Mailbox
->DebugPortHandle
,
293 (UINT8
*)mWarningMsgIgnoreSmmEntryBreak
,
294 AsciiStrLen (mWarningMsgIgnoreSmmEntryBreak
)
298 // If SMM entry break is set, SMM code will be break at here.
305 case DEBUG_AGENT_INIT_EXIT_SMI
:
306 Mailbox
= GetMailboxPointer ();
308 // Clear Skip Breakpoint flag
310 mSkipBreakpoint
= FALSE
;
311 RestoreDebugRegister ();
314 case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64
:
315 if (Context
== NULL
) {
316 DEBUG ((EFI_D_ERROR
, "DebugAgent: Input parameter Context cannot be NULL!\n"));
319 Ia32Idtr
= (IA32_DESCRIPTOR
*) Context
;
320 Ia32IdtEntry
= (IA32_IDT_ENTRY
*)(Ia32Idtr
->Base
);
321 MailboxLocation
= (UINT64
*) (UINTN
) (Ia32IdtEntry
[DEBUG_MAILBOX_VECTOR
].Bits
.OffsetLow
+
322 (Ia32IdtEntry
[DEBUG_MAILBOX_VECTOR
].Bits
.OffsetHigh
<< 16));
323 mMailboxPointer
= (DEBUG_AGENT_MAILBOX
*)(UINTN
)(*MailboxLocation
);
324 VerifyMailboxChecksum (mMailboxPointer
);
326 // Get original IDT address and size.
328 AsmReadIdtr ((IA32_DESCRIPTOR
*) &Idtr
);
329 IdtEntryCount
= (UINT16
) ((Idtr
.Limit
+ 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR
));
330 if (IdtEntryCount
< 33) {
331 Idtr
.Limit
= (UINT16
) (sizeof (IA32_IDT_GATE_DESCRIPTOR
) * 33 - 1);
332 Idtr
.Base
= (UINTN
) &mIdtEntryTable
;
333 ZeroMem (&mIdtEntryTable
, Idtr
.Limit
+ 1);
334 AsmWriteIdtr ((IA32_DESCRIPTOR
*) &Idtr
);
337 InitializeDebugIdt ();
339 // Initialize Debug Timer hardware and save its frequency
341 InitializeDebugTimer (&DebugTimerFrequency
);
342 UpdateMailboxContent (mMailboxPointer
, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY
, DebugTimerFrequency
);
345 FindAndReportModuleImageInfo (SIZE_4KB
);
351 // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this
352 // Debug Agent library instance.
354 DEBUG ((EFI_D_ERROR
, "Debug Agent: The InitFlag value is not allowed!\n"));