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