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 Library 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 BOOLEAN CpuInterruptState; 380 381 // 382 // Disable interrupts and save current interrupt state 383 // 384 CpuInterruptState = SaveAndDisableInterrupts(); 385 386 switch (InitFlag) { 387 388 case DEBUG_AGENT_INIT_PREMEM_SEC: 389 390 InitializeDebugIdt (); 391 392 MailboxLocation = (UINT64)(UINTN)&MailboxInStack; 393 Mailbox = &MailboxInStack; 394 ZeroMem ((VOID *) Mailbox, sizeof (DEBUG_AGENT_MAILBOX)); 395 // 396 // Get and save debug port handle and set the length of memory block. 397 // 398 SetLocationSavedMailboxPointerInIdtEntry (&MailboxLocation); 399 // 400 // Force error message could be printed during the first shakehand between Target/HOST. 401 // 402 SetDebugFlag (DEBUG_AGENT_FLAG_PRINT_ERROR_LEVEL, DEBUG_AGENT_ERROR); 403 // 404 // Save init arch type when debug agent initialized 405 // 406 SetDebugFlag (DEBUG_AGENT_FLAG_INIT_ARCH, DEBUG_ARCH_SYMBOL); 407 // 408 // Initialize Debug Timer hardware and save its frequency 409 // 410 InitializeDebugTimer (&DebugTimerFrequency, TRUE); 411 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency); 412 413 Phase2Context.InitFlag = InitFlag; 414 Phase2Context.Context = Context; 415 Phase2Context.Function = Function; 416 DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2); 417 // 418 // If reaches here, it means Debug Port initialization failed. 419 // 420 DEBUG ((EFI_D_ERROR, "Debug Agent: Debug port initialization failed.\n")); 421 422 break; 423 424 case DEBUG_AGENT_INIT_POSTMEM_SEC: 425 Mailbox = GetMailboxPointer (); 426 // 427 // Memory has been ready 428 // 429 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1); 430 if (IsHostAttached ()) { 431 // 432 // Trigger one software interrupt to inform HOST 433 // 434 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE); 435 } 436 // 437 // Install Vector Handoff Info PPI to persist vectors used by Debug Agent 438 // 439 Status = PeiServicesInstallPpi (&mVectorHandoffInfoPpiList[0]); 440 if (EFI_ERROR (Status)) { 441 DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to install Vector Handoff Info PPI!\n")); 442 CpuDeadLoop (); 443 } 444 // 445 // Fix up Debug Port handle address and mailbox address 446 // 447 DebugAgentContext = (DEBUG_AGENT_CONTEXT_POSTMEM_SEC *) Context; 448 if (DebugAgentContext != NULL) { 449 DebugPortHandle = (UINT64)(UINT32)(Mailbox->DebugPortHandle + DebugAgentContext->StackMigrateOffset); 450 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle); 451 Mailbox = (DEBUG_AGENT_MAILBOX *) ((UINTN) Mailbox + DebugAgentContext->StackMigrateOffset); 452 MailboxLocation = (UINT64)(UINTN)Mailbox; 453 // 454 // Build mailbox location in HOB and fix-up its address 455 // 456 MailboxLocationPointer = BuildGuidDataHob ( 457 &gEfiDebugAgentGuid, 458 &MailboxLocation, 459 sizeof (UINT64) 460 ); 461 MailboxLocationPointer = (UINT64 *) ((UINTN) MailboxLocationPointer + DebugAgentContext->HeapMigrateOffset); 462 } else { 463 // 464 // DebugAgentContext is NULL. Then, Mailbox can directly be copied into memory. 465 // Allocate ACPI NVS memory for new Mailbox and Debug Port Handle buffer 466 // 467 Status = PeiServicesAllocatePages ( 468 EfiACPIMemoryNVS, 469 EFI_SIZE_TO_PAGES (sizeof(DEBUG_AGENT_MAILBOX) + PcdGet16(PcdDebugPortHandleBufferSize)), 470 &Address 471 ); 472 if (EFI_ERROR (Status)) { 473 DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to allocate pages!\n")); 474 CpuDeadLoop (); 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 // Update IDT entry to save the location saved mailbox pointer 497 // 498 SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer); 499 break; 500 501 case DEBUG_AGENT_INIT_PEI: 502 if (Context == NULL) { 503 DEBUG ((EFI_D_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n")); 504 CpuDeadLoop (); 505 } 506 // 507 // Check if Debug Agent has initialized before 508 // 509 if (IsDebugAgentInitialzed()) { 510 DEBUG ((EFI_D_WARN, "Debug Agent: It has already initialized in SEC Core!\n")); 511 break; 512 } 513 // 514 // Install Vector Handoff Info PPI to persist vectors used by Debug Agent 515 // 516 Status = PeiServicesInstallPpi (&mVectorHandoffInfoPpiList[0]); 517 if (EFI_ERROR (Status)) { 518 DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to install Vector Handoff Info PPI!\n")); 519 CpuDeadLoop (); 520 } 521 // 522 // Set up IDT entries 523 // 524 InitializeDebugIdt (); 525 // 526 // Build mailbox in HOB and setup Mailbox Set In Pei flag 527 // 528 Mailbox = AllocateZeroPool (sizeof (DEBUG_AGENT_MAILBOX)); 529 if (Mailbox == NULL) { 530 DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to allocate memory!\n")); 531 CpuDeadLoop (); 532 } else { 533 MailboxLocation = (UINT64)(UINTN)Mailbox; 534 MailboxLocationPointer = BuildGuidDataHob ( 535 &gEfiDebugAgentGuid, 536 &MailboxLocation, 537 sizeof (UINT64) 538 ); 539 // 540 // Initialize Debug Timer hardware and save its frequency 541 // 542 InitializeDebugTimer (&DebugTimerFrequency, TRUE); 543 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY, DebugTimerFrequency); 544 // 545 // Update IDT entry to save the location pointer saved mailbox pointer 546 // 547 SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer); 548 } 549 // 550 // Save init arch type when debug agent initialized 551 // 552 SetDebugFlag (DEBUG_AGENT_FLAG_INIT_ARCH, DEBUG_ARCH_SYMBOL); 553 // 554 // Register for a callback once memory has been initialized. 555 // If memery has been ready, the callback funtion will be invoked immediately 556 // 557 Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList[0]); 558 if (EFI_ERROR (Status)) { 559 DEBUG ((EFI_D_ERROR, "DebugAgent: Failed to register memory discovered callback function!\n")); 560 CpuDeadLoop (); 561 } 562 // 563 // Set HOB check flag if memory has not been ready yet 564 // 565 if (GetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY) == 0) { 566 SetDebugFlag (DEBUG_AGENT_FLAG_CHECK_MAILBOX_IN_HOB, 1); 567 } 568 569 Phase2Context.InitFlag = InitFlag; 570 Phase2Context.Context = Context; 571 Phase2Context.Function = Function; 572 DebugPortInitialize ((VOID *) &Phase2Context, InitializeDebugAgentPhase2); 573 574 FindAndReportModuleImageInfo (4); 575 576 break; 577 578 case DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64: 579 if (Context == NULL) { 580 DEBUG ((EFI_D_ERROR, "DebugAgent: Input parameter Context cannot be NULL!\n")); 581 CpuDeadLoop (); 582 } else { 583 Ia32Idtr = (IA32_DESCRIPTOR *) Context; 584 Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base); 585 MailboxLocationPointer = (UINT64 *) (UINTN) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + 586 (UINT32) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16)); 587 Mailbox = (DEBUG_AGENT_MAILBOX *) (UINTN)(*MailboxLocationPointer); 588 // 589 // Mailbox should valid and setup before executing thunk code 590 // 591 VerifyMailboxChecksum (Mailbox); 592 593 DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)Mailbox->DebugPortHandle, NULL); 594 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle); 595 // 596 // Set up IDT entries 597 // 598 InitializeDebugIdt (); 599 // 600 // Update IDT entry to save location pointer saved the mailbox pointer 601 // 602 SetLocationSavedMailboxPointerInIdtEntry (MailboxLocationPointer); 603 604 FindAndReportModuleImageInfo (4); 605 } 606 break; 607 608 default: 609 // 610 // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this 611 // Debug Agent library instance. 612 // 613 DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n")); 614 CpuDeadLoop (); 615 break; 616 } 617 618 if (InitFlag == DEBUG_AGENT_INIT_POSTMEM_SEC) { 619 // 620 // Restore CPU Interrupt state and keep debug timer interrupt state as is 621 // in DEBUG_AGENT_INIT_POSTMEM_SEC case 622 // 623 SetInterruptState (CpuInterruptState); 624 } else { 625 // 626 // Enable Debug Timer interrupt 627 // 628 SaveAndSetDebugTimerInterrupt (TRUE); 629 // 630 // Enable CPU interrupts so debug timer interrupts can be delivered 631 // 632 EnableInterrupts (); 633 } 634 // 635 // If Function is not NULL, invoke it always whatever debug agent was initialized sucesssfully or not. 636 // 637 if (Function != NULL) { 638 Function (Context); 639 } 640 // 641 // Set return status for DEBUG_AGENT_INIT_PEI 642 // 643 if (InitFlag == DEBUG_AGENT_INIT_PEI && Context != NULL) { 644 *(EFI_STATUS *)Context = EFI_SUCCESS; 645 } 646 } 647 648 /** 649 Caller provided function to be invoked at the end of DebugPortInitialize(). 650 651 Refer to the description for DebugPortInitialize() for more details. 652 653 @param[in] Context The first input argument of DebugPortInitialize(). 654 @param[in] DebugPortHandle Debug port handle created by Debug Communication Library. 655 656 **/ 657 VOID 658 EFIAPI 659 InitializeDebugAgentPhase2 ( 660 IN VOID *Context, 661 IN DEBUG_PORT_HANDLE DebugPortHandle 662 ) 663 { 664 DEBUG_AGENT_PHASE2_CONTEXT *Phase2Context; 665 UINT64 *MailboxLocation; 666 DEBUG_AGENT_MAILBOX *Mailbox; 667 EFI_SEC_PEI_HAND_OFF *SecCoreData; 668 UINT16 BufferSize; 669 UINT64 NewDebugPortHandle; 670 671 Phase2Context = (DEBUG_AGENT_PHASE2_CONTEXT *) Context; 672 MailboxLocation = GetLocationSavedMailboxPointerInIdtEntry (); 673 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation); 674 BufferSize = PcdGet16(PcdDebugPortHandleBufferSize); 675 if (Phase2Context->InitFlag == DEBUG_AGENT_INIT_PEI && BufferSize != 0) { 676 NewDebugPortHandle = (UINT64)(UINTN)AllocateCopyPool (BufferSize, DebugPortHandle); 677 } else { 678 NewDebugPortHandle = (UINT64)(UINTN)DebugPortHandle; 679 } 680 UpdateMailboxContent (Mailbox, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, NewDebugPortHandle); 681 682 // 683 // Trigger one software interrupt to inform HOST 684 // 685 TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE); 686 687 if (Phase2Context->InitFlag == DEBUG_AGENT_INIT_PREMEM_SEC) { 688 // 689 // If Temporary RAM region is below 128 MB, then send message to 690 // host to disable low memory filtering. 691 // 692 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Phase2Context->Context; 693 if ((UINTN)SecCoreData->TemporaryRamBase < BASE_128MB && IsHostAttached ()) { 694 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1); 695 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE); 696 } 697 // 698 // Enable Debug Timer interrupt 699 // 700 SaveAndSetDebugTimerInterrupt (TRUE); 701 // 702 // Enable CPU interrupts so debug timer interrupts can be delivered 703 // 704 EnableInterrupts (); 705 // 706 // Call continuation function if it is not NULL. 707 // 708 Phase2Context->Function (Phase2Context->Context); 709 } 710 } 711