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