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