]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgent/SecPeiDebugAgentLib.c
Add InitFlag member in DEBUG_AGENT_PHASE2_CONTEXT to pass into InitializeDebugAgentPh...
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / SecPeiDebugAgent / SecPeiDebugAgentLib.c
CommitLineData
18b144ea 1/** @file\r
2 SEC Core Debug Agent Library instance implementition.\r
3\r
b422b62c 4 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
18b144ea 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "SecPeiDebugAgentLib.h"\r
16\r
b422b62c 17BOOLEAN mSkipBreakpoint = FALSE;\r
18\r
8cc26df4
JF
19\r
20EFI_PEI_VECTOR_HANDOFF_INFO_PPI mVectorHandoffInfoPpi = {\r
21 &mVectorHandoffInfoDebugAgent[0]\r
22};\r
23\r
24//\r
25// Ppis to be installed\r
26//\r
27EFI_PEI_PPI_DESCRIPTOR mVectorHandoffInfoPpiList[] = { \r
28 {\r
29 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
30 &gEfiVectorHandoffInfoPpiGuid,\r
31 &mVectorHandoffInfoPpi\r
32 }\r
33};\r
34\r
b422b62c 35EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[1] = {\r
36 {\r
37 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
38 &gEfiPeiMemoryDiscoveredPpiGuid,\r
39 DebugAgentCallbackMemoryDiscoveredPpi\r
40 }\r
41};\r
42\r
43/**\r
44 Check if debug agent support multi-processor.\r
45\r
46 @retval TRUE Multi-processor is supported.\r
47 @retval FALSE Multi-processor is not supported.\r
48\r
49**/\r
50BOOLEAN\r
51MultiProcessorDebugSupport (\r
52 VOID\r
53 )\r
54{\r
55 return FALSE;\r
56}\r
18b144ea 57\r
93c0bdec 58/**\r
59 Read the Attach/Break-in symbols from the debug port.\r
60\r
61 @param[in] Handle Pointer to Debug Port handle.\r
62 @param[out] BreakSymbol Returned break symbol.\r
63\r
64 @retval EFI_SUCCESS Read the symbol in BreakSymbol.\r
65 @retval EFI_NOT_FOUND No read the break symbol.\r
66\r
67**/\r
68EFI_STATUS\r
69DebugReadBreakSymbol (\r
70 IN DEBUG_PORT_HANDLE Handle,\r
71 OUT UINT8 *BreakSymbol\r
72 )\r
73{\r
b422b62c 74 EFI_STATUS Status;\r
75 DEBUG_PACKET_HEADER DebugHeader;\r
76 UINT8 *Data8;\r
77\r
93c0bdec 78 *BreakSymbol = 0;\r
79 //\r
b422b62c 80 // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer empty.\r
93c0bdec 81 //\r
b422b62c 82 Data8 = (UINT8 *) &DebugHeader;\r
83 while (TRUE) {\r
84 //\r
85 // If start symbol is not received\r
86 //\r
87 if (!DebugPortPollBuffer (Handle)) {\r
88 //\r
89 // If no data in Debug Port, exit\r
90 //\r
91 break;\r
92 }\r
93 //\r
94 // Try to read the start symbol\r
95 //\r
96 DebugPortReadBuffer (Handle, Data8, 1, 0);\r
97 if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {\r
98 *BreakSymbol = *Data8;\r
99 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *BreakSymbol);\r
93c0bdec 100 return EFI_SUCCESS;\r
b422b62c 101 } \r
102 if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {\r
103 Status = ReadRemainingBreakPacket (Handle, &DebugHeader);\r
104 if (Status == EFI_SUCCESS) {\r
105 *BreakSymbol = DebugHeader.Command;\r
106 DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer break symbol received %x", *BreakSymbol);\r
107 return EFI_SUCCESS;\r
108 }\r
109 if (Status == EFI_TIMEOUT) {\r
110 break;\r
111 }\r
93c0bdec 112 }\r
113 }\r
114 \r
115 return EFI_NOT_FOUND;\r
116}\r
117\r
18b144ea 118/**\r
b422b62c 119 Get the pointer to location saved Mailbox pointer from IDT entry.\r
18b144ea 120\r
121**/\r
122VOID *\r
b422b62c 123GetLocationSavedMailboxPointerInIdtEntry (\r
18b144ea 124 VOID\r
125 )\r
126{\r
b422b62c 127 UINTN *MailboxLocation;\r
18b144ea 128\r
b422b62c 129 MailboxLocation = (UINTN *) GetExceptionHandlerInIdtEntry (DEBUG_MAILBOX_VECTOR);\r
130 //\r
131 // *MailboxLocation is the pointer to Mailbox\r
132 //\r
133 VerifyMailboxChecksum ((DEBUG_AGENT_MAILBOX *) (*MailboxLocation));\r
134 return MailboxLocation;\r
18b144ea 135}\r
136\r
137/**\r
138 Set the pointer of Mailbox into IDT entry before memory is ready.\r
139\r
b422b62c 140 @param[in] MailboxLocation Pointer to location saved Mailbox pointer.\r
18b144ea 141\r
142**/\r
143VOID\r
b422b62c 144SetLocationSavedMailboxPointerInIdtEntry (\r
145 IN VOID *MailboxLocation\r
18b144ea 146 )\r
147{\r
b422b62c 148 SetExceptionHandlerInIdtEntry (DEBUG_MAILBOX_VECTOR, MailboxLocation);\r
18b144ea 149}\r
150\r
151/**\r
b422b62c 152 Get the location of Mailbox pointer from the GUIDed HOB.\r
18b144ea 153\r
b422b62c 154 @return Pointer to the location saved Mailbox pointer.\r
18b144ea 155\r
156**/\r
b422b62c 157UINT64 *\r
158GetMailboxLocationFromHob (\r
18b144ea 159 VOID\r
160 )\r
161{\r
b422b62c 162 EFI_HOB_GUID_TYPE *GuidHob;\r
18b144ea 163\r
b422b62c 164 GuidHob = GetFirstGuidHob (&gEfiDebugAgentGuid);\r
165 if (GuidHob == NULL) {\r
166 return NULL;\r
167 }\r
168 return (UINT64 *) (GET_GUID_HOB_DATA(GuidHob));\r
18b144ea 169}\r
170\r
171/**\r
172 Get Debug Agent Mailbox pointer.\r
173\r
174 @return Mailbox pointer.\r
175\r
176**/\r
177DEBUG_AGENT_MAILBOX *\r
178GetMailboxPointer (\r
179 VOID\r
180 )\r
181{\r
b422b62c 182 UINT64 DebugPortHandle;\r
183 UINT64 *MailboxLocationInIdt;\r
184 UINT64 *MailboxLocationInHob;\r
185 DEBUG_AGENT_MAILBOX *Mailbox;\r
186 \r
187 //\r
188 // Get mailbox from IDT entry firstly\r
189 //\r
190 MailboxLocationInIdt = GetLocationSavedMailboxPointerInIdtEntry ();\r
191 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocationInIdt);\r
192 //\r
0a488765 193 // Cannot used GetDebugFlag() to get Debug Flag to avoid GetMailboxPointer() nested\r
b422b62c 194 //\r
0a488765 195 if (Mailbox->DebugFlag.Bits.CheckMailboxInHob != 1 ||\r
196 Mailbox->DebugFlag.Bits.InitArch != DEBUG_ARCH_SYMBOL) {\r
b422b62c 197 //\r
0a488765 198 // If mailbox was setup in SEC or the current CPU arch is different from the init arch\r
199 // Debug Agent initialized, return the mailbox from IDT entry directly.\r
200 // Otherwise, we need to check the mailbox location saved in GUIDed HOB further.\r
201 // \r
b422b62c 202 return Mailbox;\r
203 }\r
204\r
205 MailboxLocationInHob = GetMailboxLocationFromHob ();\r
206 //\r
0a488765 207 // Compare mailbox in IDT enry with mailbox in HOB,\r
208 // need to fix mailbox location if HOB moved by PEI CORE\r
b422b62c 209 //\r
210 if (MailboxLocationInHob != MailboxLocationInIdt && MailboxLocationInHob != NULL) {\r
211 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocationInHob);\r
212 //\r
213 // Fix up Debug Port handler and save new mailbox in IDT entry\r
214 //\r
215 Mailbox = (DEBUG_AGENT_MAILBOX *)((UINTN)Mailbox + ((UINTN)(MailboxLocationInHob) - (UINTN)MailboxLocationInIdt));\r
216 DebugPortHandle = (UINT64)((UINTN)Mailbox->DebugPortHandle + ((UINTN)(MailboxLocationInHob) - (UINTN)MailboxLocationInIdt));\r
217 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
218 *MailboxLocationInHob = (UINT64)(UINTN)Mailbox;\r
219 SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationInHob);\r
220 //\r
221 // Clean CheckMailboxInHob flag\r
222 //\r
223 Mailbox->DebugFlag.Bits.CheckMailboxInHob = 0;\r
224 UpdateMailboxChecksum (Mailbox);\r
225 }\r
226\r
227 return Mailbox;\r
18b144ea 228}\r
229\r
230/**\r
231 Get debug port handle.\r
232\r
233 @return Debug port handle.\r
234\r
235**/\r
236DEBUG_PORT_HANDLE\r
237GetDebugPortHandle (\r
238 VOID\r
239 )\r
240{\r
241 DEBUG_AGENT_MAILBOX *DebugAgentMailbox;\r
242 \r
b422b62c 243 DebugAgentMailbox = GetMailboxPointer ();\r
18b144ea 244\r
245 return (DEBUG_PORT_HANDLE) (UINTN)(DebugAgentMailbox->DebugPortHandle);\r
246}\r
247\r
248/**\r
b422b62c 249 Debug Agent provided notify callback function on Memory Discovered PPI.\r
250\r
251 @param[in] PeiServices Indirect reference to the PEI Services Table.\r
252 @param[in] NotifyDescriptor Address of the notification descriptor data structure.\r
253 @param[in] Ppi Address of the PPI that was installed.\r
18b144ea 254\r
b422b62c 255 @retval EFI_SUCCESS If the function completed successfully.\r
18b144ea 256\r
257**/\r
b422b62c 258EFI_STATUS\r
259EFIAPI\r
260DebugAgentCallbackMemoryDiscoveredPpi (\r
261 IN EFI_PEI_SERVICES **PeiServices,\r
262 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
263 IN VOID *Ppi\r
18b144ea 264 )\r
265{\r
dca18202 266 EFI_STATUS Status;\r
b422b62c 267 DEBUG_AGENT_MAILBOX *Mailbox;\r
268 BOOLEAN InterruptStatus;\r
0a488765 269 EFI_PHYSICAL_ADDRESS Address; \r
dca18202 270 DEBUG_AGENT_MAILBOX *NewMailbox;\r
271 UINT64 *MailboxLocationInHob;\r
272\r
18b144ea 273 //\r
b422b62c 274 // Save and disable original interrupt status\r
18b144ea 275 //\r
b422b62c 276 InterruptStatus = SaveAndDisableInterrupts ();\r
dca18202 277\r
18b144ea 278 //\r
dca18202 279 // Allocate ACPI NVS memory for new Mailbox and Debug Port Handle buffer\r
280 //\r
281 Status = PeiServicesAllocatePages (\r
282 EfiACPIMemoryNVS,\r
283 EFI_SIZE_TO_PAGES (sizeof(DEBUG_AGENT_MAILBOX) + PcdGet16(PcdDebugPortHandleBufferSize)),\r
0a488765 284 &Address\r
dca18202 285 );\r
286 ASSERT_EFI_ERROR (Status);\r
0a488765 287 NewMailbox = (DEBUG_AGENT_MAILBOX *) (UINTN) Address;\r
dca18202 288 //\r
289 // Copy Mailbox and Debug Port Handle buffer to new location in ACPI NVS memory, because original Mailbox\r
290 // and Debug Port Handle buffer in the allocated pool that may be marked as free by DXE Core after DXE Core\r
291 // reallocates the HOB.\r
18b144ea 292 //\r
b422b62c 293 Mailbox = GetMailboxPointer ();\r
dca18202 294 CopyMem (NewMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
295 CopyMem (NewMailbox + 1, (VOID *)(UINTN)Mailbox->DebugPortHandle, PcdGet16(PcdDebugPortHandleBufferSize));\r
18b144ea 296 //\r
dca18202 297 // Update Mailbox Location pointer in GUIDed HOB and IDT entry with new one\r
18b144ea 298 //\r
dca18202 299 MailboxLocationInHob = GetMailboxLocationFromHob ();\r
8cbad981 300 ASSERT (MailboxLocationInHob != NULL);\r
dca18202 301 *MailboxLocationInHob = (UINT64)(UINTN)NewMailbox;\r
302 SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationInHob);\r
303 //\r
304 // Update Debug Port Handle in new Mailbox\r
305 //\r
306 UpdateMailboxContent (NewMailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, (UINT64)(UINTN)(NewMailbox + 1));\r
307 //\r
308 // Set physical memory ready flag\r
309 //\r
310 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
311\r
b422b62c 312 if (IsHostAttached ()) {\r
313 //\r
314 // Trigger one software interrupt to inform HOST\r
315 //\r
316 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
317 }\r
18b144ea 318\r
319 //\r
b422b62c 320 // Restore interrupt state.\r
18b144ea 321 //\r
b422b62c 322 SetInterruptState (InterruptStatus);\r
323 \r
324 return EFI_SUCCESS;\r
18b144ea 325}\r
326\r
327/**\r
328 Initialize debug agent.\r
329\r
330 This function is used to set up debug environment for SEC and PEI phase.\r
331\r
332 If InitFlag is DEBUG_AGENT_INIT_PREMEM_SEC, it will overirde IDT table entries\r
333 and initialize debug port. It will enable interrupt to support break-in feature.\r
334 It will set up debug agent Mailbox in cache-as-ramfrom. It will be called before\r
335 physical memory is ready.\r
336 If InitFlag is DEBUG_AGENT_INIT_POSTMEM_SEC, debug agent will build one GUIDed\r
337 HOB to copy debug agent Mailbox. It will be called after physical memory is ready.\r
338\r
339 This function is used to set up debug environment to support source level debugging.\r
340 If certain Debug Agent Library instance has to save some private data in the stack,\r
341 this function must work on the mode that doesn't return to the caller, then\r
342 the caller needs to wrap up all rest of logic after InitializeDebugAgent() into one\r
343 function and pass it into InitializeDebugAgent(). InitializeDebugAgent() is\r
344 responsible to invoke the passing-in function at the end of InitializeDebugAgent().\r
345\r
346 If the parameter Function is not NULL, Debug Agent Libary instance will invoke it by\r
347 passing in the Context to be its parameter.\r
348\r
349 If Function() is NULL, Debug Agent Library instance will return after setup debug\r
350 environment.\r
351\r
352 @param[in] InitFlag Init flag is used to decide the initialize process.\r
353 @param[in] Context Context needed according to InitFlag; it was optional.\r
354 @param[in] Function Continue function called by debug agent library; it was\r
355 optional.\r
356\r
357**/\r
358VOID\r
359EFIAPI\r
360InitializeDebugAgent (\r
361 IN UINT32 InitFlag,\r
362 IN VOID *Context, OPTIONAL\r
363 IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
364 )\r
365{\r
366 DEBUG_AGENT_MAILBOX *Mailbox;\r
4d0da5fb 367 DEBUG_AGENT_MAILBOX *NewMailbox;\r
18b144ea 368 DEBUG_AGENT_MAILBOX MailboxInStack;\r
369 DEBUG_AGENT_PHASE2_CONTEXT Phase2Context;\r
370 DEBUG_AGENT_CONTEXT_POSTMEM_SEC *DebugAgentContext;\r
b422b62c 371 EFI_STATUS Status;\r
372 IA32_DESCRIPTOR *Ia32Idtr;\r
373 IA32_IDT_ENTRY *Ia32IdtEntry;\r
374 UINT64 DebugPortHandle;\r
375 UINT64 MailboxLocation;\r
376 UINT64 *MailboxLocationPointer;\r
4d0da5fb 377 EFI_PHYSICAL_ADDRESS Address; \r
b422b62c 378 \r
18b144ea 379 DisableInterrupts ();\r
380\r
e2104834 381 switch (InitFlag) {\r
382\r
383 case DEBUG_AGENT_INIT_PREMEM_SEC:\r
384\r
385 InitializeDebugIdt ();\r
386\r
b422b62c 387 MailboxLocation = (UINT64)(UINTN)&MailboxInStack;\r
e2104834 388 Mailbox = &MailboxInStack;\r
389 ZeroMem ((VOID *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
e2104834 390 //\r
391 // Get and save debug port handle and set the length of memory block.\r
392 //\r
b422b62c 393 SetLocationSavedMailboxPointerInIdtEntry (&MailboxLocation);\r
0a488765 394 //\r
395 // Force error message could be printed during the first shakehand between Target/HOST.\r
396 //\r
b422b62c 397 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DEBUG_AGENT_ERROR);\r
0a488765 398 //\r
399 // Save init arch type when debug agent initialized\r
400 //\r
b6d1508f 401 SetDebugFlag (DEBUG_AGENT_FLAG_INIT_ARCH, DEBUG_ARCH_SYMBOL);\r
e2104834 402\r
403 InitializeDebugTimer ();\r
404\r
5ab7f883 405 Phase2Context.InitFlag = InitFlag;\r
e2104834 406 Phase2Context.Context = Context;\r
407 Phase2Context.Function = Function;\r
408 DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2);\r
e2104834 409 //\r
410 // If reaches here, it means Debug Port initialization failed.\r
411 //\r
412 DEBUG ((EFI_D_ERROR, "Debug Agent: Debug port initialization failed.\n"));\r
413\r
414 break;\r
415\r
416 case DEBUG_AGENT_INIT_POSTMEM_SEC:\r
b422b62c 417 Mailbox = GetMailboxPointer ();\r
18b144ea 418 //\r
419 // Memory has been ready\r
420 //\r
b422b62c 421 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
422 if (IsHostAttached ()) {\r
18b144ea 423 //\r
424 // Trigger one software interrupt to inform HOST\r
425 //\r
426 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
427 }\r
8cc26df4
JF
428 //\r
429 // Install Vector Handoff Info PPI to persist vectors used by Debug Agent\r
430 //\r
431 Status = PeiServicesInstallPpi (&mVectorHandoffInfoPpiList[0]);\r
432 if (EFI_ERROR (Status)) {\r
433 DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to install Vector Handoff Info PPI!\n"));\r
434 CpuDeadLoop ();\r
435 }\r
b422b62c 436 //\r
437 // Fix up Debug Port handle address and mailbox address\r
438 //\r
18b144ea 439 DebugAgentContext = (DEBUG_AGENT_CONTEXT_POSTMEM_SEC *) Context;\r
4d0da5fb
LG
440 if (DebugAgentContext != NULL) {\r
441 DebugPortHandle = (UINT64)(UINT32)(Mailbox->DebugPortHandle + DebugAgentContext->StackMigrateOffset);\r
442 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
443 Mailbox = (DEBUG_AGENT_MAILBOX *) ((UINTN) Mailbox + DebugAgentContext->StackMigrateOffset);\r
444 MailboxLocation = (UINT64)(UINTN)Mailbox;\r
445 //\r
446 // Build mailbox location in HOB and fix-up its address\r
447 //\r
448 MailboxLocationPointer = BuildGuidDataHob (\r
449 &gEfiDebugAgentGuid,\r
450 &MailboxLocation,\r
451 sizeof (UINT64)\r
452 );\r
453 MailboxLocationPointer = (UINT64 *) ((UINTN) MailboxLocationPointer + DebugAgentContext->HeapMigrateOffset);\r
454 } else {\r
455 //\r
456 // DebugAgentContext is NULL. Then, Mailbox can directly be copied into memory.\r
457 // Allocate ACPI NVS memory for new Mailbox and Debug Port Handle buffer\r
458 //\r
459 Status = PeiServicesAllocatePages (\r
460 EfiACPIMemoryNVS,\r
461 EFI_SIZE_TO_PAGES (sizeof(DEBUG_AGENT_MAILBOX) + PcdGet16(PcdDebugPortHandleBufferSize)),\r
462 &Address\r
463 );\r
8cc26df4
JF
464 if (EFI_ERROR (Status)) {\r
465 DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to allocate pages!\n"));\r
466 CpuDeadLoop ();\r
467 }\r
4d0da5fb
LG
468 NewMailbox = (DEBUG_AGENT_MAILBOX *) (UINTN) Address;\r
469 //\r
470 // Copy Mailbox and Debug Port Handle buffer to new location in ACPI NVS memory, because original Mailbox\r
471 // and Debug Port Handle buffer in the allocated pool that may be marked as free by DXE Core after DXE Core\r
472 // reallocates the HOB.\r
473 //\r
474 CopyMem (NewMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
475 CopyMem (NewMailbox + 1, (VOID *)(UINTN)Mailbox->DebugPortHandle, PcdGet16(PcdDebugPortHandleBufferSize));\r
476 UpdateMailboxContent (NewMailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, (UINT64)(UINTN)(NewMailbox + 1));\r
477 MailboxLocation = (UINT64)(UINTN)NewMailbox;\r
478 //\r
479 // Build mailbox location in HOB\r
480 //\r
481 MailboxLocationPointer = BuildGuidDataHob (\r
482 &gEfiDebugAgentGuid,\r
483 &MailboxLocation,\r
484 sizeof (UINT64)\r
485 );\r
486 }\r
b422b62c 487 //\r
488 // Update IDT entry to save the location saved mailbox pointer\r
489 //\r
490 SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);\r
b422b62c 491 break;\r
492\r
493 case DEBUG_AGENT_INIT_PEI:\r
5ab7f883
JF
494 if (Context == NULL) {\r
495 DEBUG ((EFI_D_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n"));\r
496 CpuDeadLoop ();\r
497 }\r
b422b62c 498 //\r
499 // Check if Debug Agent has initialized before\r
500 //\r
501 if (IsDebugAgentInitialzed()) {\r
502 DEBUG ((EFI_D_WARN, "Debug Agent: It has already initialized in SEC Core!\n"));\r
503 break;\r
504 }\r
505 //\r
8cc26df4
JF
506 // Install Vector Handoff Info PPI to persist vectors used by Debug Agent\r
507 //\r
508 Status = PeiServicesInstallPpi (&mVectorHandoffInfoPpiList[0]);\r
509 if (EFI_ERROR (Status)) {\r
510 DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to install Vector Handoff Info PPI!\n"));\r
511 CpuDeadLoop ();\r
512 }\r
513 //\r
b422b62c 514 // Set up IDT entries\r
515 //\r
516 InitializeDebugIdt ();\r
517 //\r
518 // Build mailbox in HOB and setup Mailbox Set In Pei flag\r
519 //\r
520 Mailbox = AllocateZeroPool (sizeof (DEBUG_AGENT_MAILBOX));\r
521 MailboxLocation = (UINT64)(UINTN)Mailbox;\r
522 MailboxLocationPointer = BuildGuidDataHob (\r
523 &gEfiDebugAgentGuid,\r
524 &MailboxLocation,\r
525 sizeof (UINT64)\r
526 );\r
18b144ea 527\r
b422b62c 528 InitializeDebugTimer ();\r
529 //\r
530 // Update IDT entry to save the location pointer saved mailbox pointer\r
531 //\r
532 SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);\r
533 //\r
0a488765 534 // Save init arch type when debug agent initialized\r
535 //\r
536 SetDebugFlag (DEBUG_AGENT_FLAG_INIT_ARCH, DEBUG_ARCH_SYMBOL);\r
537 //\r
b422b62c 538 // Register for a callback once memory has been initialized.\r
539 // If memery has been ready, the callback funtion will be invoked immediately\r
540 //\r
541 Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList[0]);\r
8cc26df4
JF
542 if (EFI_ERROR (Status)) {\r
543 DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to register memory discovered callback function!\n"));\r
544 CpuDeadLoop ();\r
545 }\r
b422b62c 546 //\r
547 // Set HOB check flag if memory has not been ready yet\r
548 //\r
549 if (GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY) == 0) {\r
550 SetDebugFlag (DEBUG_AGENT_FLAG_CHECK_MAILBOX_IN_HOB, 1);\r
551 }\r
18b144ea 552\r
5ab7f883 553 Phase2Context.InitFlag = InitFlag;\r
b422b62c 554 Phase2Context.Context = Context;\r
555 Phase2Context.Function = Function;\r
556 DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2);\r
18b144ea 557\r
b422b62c 558 FindAndReportModuleImageInfo (4);\r
18b144ea 559\r
b422b62c 560 break;\r
18b144ea 561\r
b422b62c 562 case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64:\r
563 if (Context == NULL) {\r
564 DEBUG ((EFI_D_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n"));\r
565 CpuDeadLoop ();\r
566 } else {\r
567 Ia32Idtr = (IA32_DESCRIPTOR *) Context;\r
568 Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);\r
569 MailboxLocationPointer = (UINT64 *) (UINTN) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow +\r
570 (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));\r
571 Mailbox = (DEBUG_AGENT_MAILBOX *) (UINTN)(*MailboxLocationPointer);\r
0a488765 572 //\r
573 // Mailbox should valid and setup before executing thunk code\r
574 //\r
b422b62c 575 VerifyMailboxChecksum (Mailbox);\r
576\r
577 DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)Mailbox->DebugPortHandle, NULL);\r
578 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
579 //\r
580 // Set up IDT entries\r
581 //\r
582 InitializeDebugIdt ();\r
583 //\r
584 // Update IDT entry to save location pointer saved the mailbox pointer\r
585 //\r
586 SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer);\r
587\r
588 FindAndReportModuleImageInfo (4);\r
589 }\r
e2104834 590 break;\r
18b144ea 591\r
e2104834 592 default:\r
18b144ea 593 //\r
e2104834 594 // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this \r
595 // Debug Agent library instance.\r
18b144ea 596 //\r
e2104834 597 DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));\r
598 CpuDeadLoop ();\r
599 break;\r
e2104834 600 }\r
18b144ea 601\r
5ab7f883
JF
602 //\r
603 // Enable CPU interrupts so debug timer interrupts can be delivered\r
604 //\r
b422b62c 605 EnableInterrupts ();\r
606\r
e2104834 607 //\r
608 // If Function is not NULL, invoke it always whatever debug agent was initialized sucesssfully or not.\r
609 //\r
610 if (Function != NULL) {\r
611 Function (Context);\r
18b144ea 612 }\r
5ab7f883
JF
613 //\r
614 // Set return status for DEBUG_AGENT_INIT_PEI\r
615 //\r
616 if (InitFlag == DEBUG_AGENT_INIT_PEI) {\r
617 *(EFI_STATUS *)Context = EFI_SUCCESS;\r
618 }\r
18b144ea 619}\r
620\r
621/**\r
622 Caller provided function to be invoked at the end of DebugPortInitialize().\r
623\r
624 Refer to the descrption for DebugPortInitialize() for more details.\r
625\r
626 @param[in] Context The first input argument of DebugPortInitialize().\r
627 @param[in] DebugPortHandle Debug port handle created by Debug Communication Libary.\r
628\r
629**/\r
630VOID\r
631EFIAPI\r
632InitializeDebugAgentPhase2 (\r
633 IN VOID *Context,\r
634 IN DEBUG_PORT_HANDLE DebugPortHandle\r
635 )\r
636{\r
637 DEBUG_AGENT_PHASE2_CONTEXT *Phase2Context;\r
b422b62c 638 UINT64 *MailboxLocation;\r
18b144ea 639 DEBUG_AGENT_MAILBOX *Mailbox;\r
640 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
b422b62c 641 UINT16 BufferSize;\r
642 UINT64 NewDebugPortHandle;\r
18b144ea 643\r
b422b62c 644 Phase2Context = (DEBUG_AGENT_PHASE2_CONTEXT *) Context;\r
645 MailboxLocation = GetLocationSavedMailboxPointerInIdtEntry ();\r
646 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
647 BufferSize = PcdGet16(PcdDebugPortHandleBufferSize);\r
5ab7f883 648 if (Phase2Context->InitFlag == DEBUG_AGENT_INIT_PEI) {\r
b422b62c 649 NewDebugPortHandle = (UINT64)(UINTN)AllocateCopyPool (BufferSize, DebugPortHandle);\r
650 } else {\r
651 NewDebugPortHandle = (UINT64)(UINTN)DebugPortHandle;\r
652 }\r
653 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, NewDebugPortHandle);\r
18b144ea 654\r
655 //\r
656 // Trigger one software interrupt to inform HOST\r
657 //\r
658 TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);\r
659\r
5ab7f883
JF
660 if (Phase2Context->InitFlag == DEBUG_AGENT_INIT_PREMEM_SEC) {\r
661 //\r
662 // If Temporary RAM region is below 128 MB, then send message to \r
663 // host to disable low memory filtering.\r
664 //\r
665 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Phase2Context->Context;\r
666 if ((UINTN)SecCoreData->TemporaryRamBase < BASE_128MB && IsHostAttached ()) {\r
667 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
668 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
669 }\r
670 //\r
671 // Enable CPU interrupts so debug timer interrupts can be delivered\r
672 //\r
673 EnableInterrupts ();\r
674 //\r
675 // Call continuation function if it is not NULL.\r
676 //\r
18b144ea 677 Phase2Context->Function (Phase2Context->Context);\r
678 }\r
679}\r