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