]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c
This revision can only work with Intel(c) UDK Debugger Tool version 1.2 or greater...
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / SecPeiDebugAgent / SecPeiDebugAgentLib.c
1 /** @file
2 SEC Core Debug Agent Library instance implementition.
3
4 Copyright (c) 2010 - 2012, 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.
9
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.
12
13 **/
14
15 #include "SecPeiDebugAgentLib.h"
16
17 CONST BOOLEAN MultiProcessorDebugSupport = FALSE;
18
19 /**
20 Read the Attach/Break-in symbols from the debug port.
21
22 @param[in] Handle Pointer to Debug Port handle.
23 @param[out] BreakSymbol Returned break symbol.
24
25 @retval EFI_SUCCESS Read the symbol in BreakSymbol.
26 @retval EFI_NOT_FOUND No read the break symbol.
27
28 **/
29 EFI_STATUS
30 DebugReadBreakSymbol (
31 IN DEBUG_PORT_HANDLE Handle,
32 OUT UINT8 *BreakSymbol
33 )
34 {
35 *BreakSymbol = 0;
36 //
37 // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer emty.
38 //
39 while (DebugPortPollBuffer (Handle)) {
40 DebugPortReadBuffer (Handle, BreakSymbol, 1, 0);
41 if (*BreakSymbol == DEBUG_STARTING_SYMBOL_ATTACH || *BreakSymbol == DEBUG_STARTING_SYMBOL_BREAK) {
42 return EFI_SUCCESS;
43 }
44 }
45
46 return EFI_NOT_FOUND;
47 }
48
49 /**
50 Get pointer to Mailbox from IDT entry before memory is ready.
51
52 **/
53 VOID *
54 GetMailboxPointerInIdtEntry (
55 VOID
56 )
57 {
58 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
59 IA32_DESCRIPTOR IdtDescriptor;
60 UINTN Mailbox;
61
62 AsmReadIdtr (&IdtDescriptor);
63 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
64
65 Mailbox = IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + (IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16);
66 return (VOID *) Mailbox;
67 }
68
69 /**
70 Set the pointer of Mailbox into IDT entry before memory is ready.
71
72 @param[in] Mailbox The pointer of Mailbox.
73
74 **/
75 VOID
76 SetMailboxPointerInIdtEntry (
77 IN VOID *Mailbox
78 )
79 {
80 IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
81 IA32_DESCRIPTOR IdtDescriptor;
82
83 AsmReadIdtr (&IdtDescriptor);
84 IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;
85
86 IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow = (UINT16)(UINTN)Mailbox;
87 IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh = (UINT16)((UINTN)Mailbox >> 16);
88 }
89
90 /**
91 Get the pointer to Mailbox from IDT entry and build the Mailbox into GUIDed Hob
92 after memory is ready.
93
94 @return Pointer to Mailbox.
95
96 **/
97 DEBUG_AGENT_MAILBOX *
98 BuildMailboxHob (
99 VOID
100 )
101 {
102 DEBUG_AGENT_MAILBOX *Mailbox;
103
104 Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();
105
106 return BuildGuidDataHob (
107 &gEfiDebugAgentGuid,
108 Mailbox,
109 sizeof (DEBUG_AGENT_MAILBOX)
110 );
111 }
112
113 /**
114 Get Debug Agent Mailbox pointer.
115
116 @return Mailbox pointer.
117
118 **/
119 DEBUG_AGENT_MAILBOX *
120 GetMailboxPointer (
121 VOID
122 )
123 {
124 return (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();
125 }
126
127 /**
128 Get debug port handle.
129
130 @return Debug port handle.
131
132 **/
133 DEBUG_PORT_HANDLE
134 GetDebugPortHandle (
135 VOID
136 )
137 {
138 DEBUG_AGENT_MAILBOX *DebugAgentMailbox;
139
140 DebugAgentMailbox = (DEBUG_AGENT_MAILBOX *)GetMailboxPointerInIdtEntry ();
141
142 return (DEBUG_PORT_HANDLE) (UINTN)(DebugAgentMailbox->DebugPortHandle);
143 }
144
145 /**
146 Trigger one software interrupt to debug agent to handle it.
147
148 @param Signature Software interrupt signature.
149
150 **/
151 VOID
152 TriggerSoftInterrupt (
153 UINT32 Signature
154 )
155 {
156 UINTN Dr0;
157 UINTN Dr1;
158
159 //
160 // Save Debug Register State
161 //
162 Dr0 = AsmReadDr0 ();
163 Dr1 = AsmReadDr1 ();
164
165 //
166 // DR0 = Signature
167 //
168 AsmWriteDr0 (SOFT_INTERRUPT_SIGNATURE);
169 AsmWriteDr1 (Signature);
170
171 //
172 // Do INT3 to communicate with HOST side
173 //
174 CpuBreakpoint ();
175
176 //
177 // Restore Debug Register State only when Host didn't change it inside exception handler.
178 // Dr registers can only be changed by setting the HW breakpoint.
179 //
180 AsmWriteDr0 (Dr0);
181 AsmWriteDr1 (Dr1);
182
183 }
184
185 /**
186 Initialize debug agent.
187
188 This function is used to set up debug environment for SEC and PEI phase.
189
190 If InitFlag is DEBUG_AGENT_INIT_PREMEM_SEC, it will overirde IDT table entries
191 and initialize debug port. It will enable interrupt to support break-in feature.
192 It will set up debug agent Mailbox in cache-as-ramfrom. It will be called before
193 physical memory is ready.
194 If InitFlag is DEBUG_AGENT_INIT_POSTMEM_SEC, debug agent will build one GUIDed
195 HOB to copy debug agent Mailbox. It will be called after physical memory is ready.
196
197 This function is used to set up debug environment to support source level debugging.
198 If certain Debug Agent Library instance has to save some private data in the stack,
199 this function must work on the mode that doesn't return to the caller, then
200 the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one
201 function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is
202 responsible to invoke the passing-in function at the end of InitializeDebugAgent().
203
204 If the parameter Function is not NULL, Debug Agent Libary instance will invoke it by
205 passing in the Context to be its parameter.
206
207 If Function() is NULL, Debug Agent Library instance will return after setup debug
208 environment.
209
210 @param[in] InitFlag Init flag is used to decide the initialize process.
211 @param[in] Context Context needed according to InitFlag; it was optional.
212 @param[in] Function Continue function called by debug agent library; it was
213 optional.
214
215 **/
216 VOID
217 EFIAPI
218 InitializeDebugAgent (
219 IN UINT32 InitFlag,
220 IN VOID *Context, OPTIONAL
221 IN DEBUG_AGENT_CONTINUE Function OPTIONAL
222 )
223 {
224 DEBUG_AGENT_MAILBOX *Mailbox;
225 DEBUG_AGENT_MAILBOX MailboxInStack;
226 DEBUG_AGENT_PHASE2_CONTEXT Phase2Context;
227 DEBUG_AGENT_CONTEXT_POSTMEM_SEC *DebugAgentContext;
228
229 DisableInterrupts ();
230
231 switch (InitFlag) {
232
233 case DEBUG_AGENT_INIT_PREMEM_SEC:
234
235 InitializeDebugIdt ();
236
237 Mailbox = &MailboxInStack;
238 ZeroMem ((VOID *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
239
240 //
241 // Get and save debug port handle and set the length of memory block.
242 //
243 SetMailboxPointerInIdtEntry ((VOID *) Mailbox);
244
245 InitializeDebugTimer ();
246
247 Phase2Context.Context = Context;
248 Phase2Context.Function = Function;
249 DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2);
250
251 //
252 // If reaches here, it means Debug Port initialization failed.
253 //
254 DEBUG ((EFI_D_ERROR, "Debug Agent: Debug port initialization failed.\n"));
255
256 break;
257
258 case DEBUG_AGENT_INIT_POSTMEM_SEC:
259
260 //
261 // Memory has been ready
262 //
263 if (IsHostAttached()) {
264 //
265 // Trigger one software interrupt to inform HOST
266 //
267 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
268 }
269
270 DebugAgentContext = (DEBUG_AGENT_CONTEXT_POSTMEM_SEC *) Context;
271
272 Mailbox = (DEBUG_AGENT_MAILBOX *) GetMailboxPointerInIdtEntry ();
273 Mailbox->DebugPortHandle = (UINT64)(UINT32)(Mailbox->DebugPortHandle + DebugAgentContext->StackMigrateOffset);
274 Mailbox->DebugFlag.MemoryReady = 1;
275
276 Mailbox = BuildMailboxHob ();
277 Mailbox = (DEBUG_AGENT_MAILBOX *) ((UINTN) Mailbox + DebugAgentContext->HeapMigrateOffset);
278
279 SetMailboxPointerInIdtEntry ((VOID *) Mailbox);
280
281 EnableInterrupts ();
282
283 break;
284
285 default:
286
287 //
288 // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this
289 // Debug Agent library instance.
290 //
291 DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));
292 CpuDeadLoop ();
293 break;
294
295 }
296
297 //
298 // If Function is not NULL, invoke it always whatever debug agent was initialized sucesssfully or not.
299 //
300 if (Function != NULL) {
301 Function (Context);
302 }
303 }
304
305 /**
306 Caller provided function to be invoked at the end of DebugPortInitialize().
307
308 Refer to the descrption for DebugPortInitialize() for more details.
309
310 @param[in] Context The first input argument of DebugPortInitialize().
311 @param[in] DebugPortHandle Debug port handle created by Debug Communication Libary.
312
313 **/
314 VOID
315 EFIAPI
316 InitializeDebugAgentPhase2 (
317 IN VOID *Context,
318 IN DEBUG_PORT_HANDLE DebugPortHandle
319 )
320 {
321 DEBUG_AGENT_PHASE2_CONTEXT *Phase2Context;
322 DEBUG_AGENT_MAILBOX *Mailbox;
323 EFI_SEC_PEI_HAND_OFF *SecCoreData;
324
325 Mailbox = GetMailboxPointerInIdtEntry ();
326 Mailbox->DebugPortHandle = (UINT64) (UINTN)DebugPortHandle;
327
328 //
329 // Trigger one software interrupt to inform HOST
330 //
331 TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);
332
333 //
334 // If Temporary RAM region is below 128 MB, then send message to
335 // host to disable low memory filtering.
336 //
337 Phase2Context = (DEBUG_AGENT_PHASE2_CONTEXT *) Context;
338 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Phase2Context->Context;
339 if ((UINTN)SecCoreData->TemporaryRamBase < BASE_128MB && IsHostAttached ()) {
340 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);
341 }
342
343 //
344 // Enable CPU interrupts so debug timer interrupts can be delivered
345 //
346 EnableInterrupts ();
347
348 //
349 // Call continuation function if it is not NULL.
350 //
351 if (Phase2Context->Function != NULL) {
352 Phase2Context->Function (Phase2Context->Context);
353 }
354 }