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