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