4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PE/Coff Extra Action library instances.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Base.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/PeCoffExtraActionLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/DebugLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/BaseLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/IoLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/PcdLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <ImageDebugSupport.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT 1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3 2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param RegisterIndex Index of Dr register. The value range is from 0 to 3.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Dr7 Value of Dr7 register.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return TRUE The hardware breakpoint specified in the Drx is enabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return FALSE The hardware breakpoint specified in the Drx is disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIsDrxEnabled (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 RegisterIndex,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Dr7
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (BOOLEAN) (((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Performs additional actions after a PE/COFF image has been loaded and relocated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If ImageContext is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageContext Pointer to the image context structure that describes the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PE/COFF image that has already been loaded and relocated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderRelocateImageExtraAction (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN InterruptState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr3;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr7;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Cr4;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN NewDr7;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 LoadImageMethod;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 DebugAgentStatus;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (ImageContext != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->PdbPointer != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((EFI_D_ERROR, " PDB = %a\n", ImageContext->PdbPointer));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Disable interrupts and save the current interrupt state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InterruptState = SaveAndDisableInterrupts ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Save Debug Register State
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr0 = AsmReadDr0 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr1 = AsmReadDr1 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr2 = AsmReadDr2 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr3 = AsmReadDr3 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr7 = AsmReadDr7 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Cr4 = AsmReadCr4 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR0 = IMAGE_LOAD_SIGNATURE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR2 = The pointer to the ImageContext structure
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR3 = IO_PORT_BREAKPOINT_ADDRESS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // CR4 = Make sure DE(BIT3) is set
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr7 (0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr0 (IMAGE_LOAD_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr1 ((UINTN)ImageContext->PdbPointer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr2 ((UINTN)ImageContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr7 (0x20000480);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteCr4 (Cr4 | BIT3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // returns a read value other than DEBUG_AGENT_IMAGE_WAIT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generate a software break point.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CpuBreakpoint ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Restore Debug Register State only when Host didn't change it inside exception handler.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // E.g.: User halts the target and sets the HW breakpoint while target is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in the above exception handler
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewDr7 = AsmReadDr7 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDrxEnabled (0, NewDr7)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr0 (Dr0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDrxEnabled (1, NewDr7)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr1 (Dr1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDrxEnabled (2, NewDr7)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr2 (Dr2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDrxEnabled (3, NewDr7)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr3 (Dr3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AsmReadCr4 () == (Cr4 | BIT3)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteCr4 (Cr4);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NewDr7 == 0x20000480) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr7 (Dr7);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Restore the interrupt state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetInterruptState (InterruptState);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Performs additional actions just before a PE/COFF image is unloaded. Any resources
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If ImageContext is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param ImageContext Pointer to the image context structure that describes the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PE/COFF image that is being unloaded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderUnloadImageExtraAction (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN InterruptState;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr3;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Dr7;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Cr4;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN NewDr7;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 LoadImageMethod;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 DebugAgentStatus;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (ImageContext != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ImageContext->PdbPointer != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG((EFI_D_ERROR, " PDB = %a\n", ImageContext->PdbPointer));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Disable interrupts and save the current interrupt state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InterruptState = SaveAndDisableInterrupts ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Save Debug Register State
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr0 = AsmReadDr0 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr1 = AsmReadDr1 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr2 = AsmReadDr2 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr3 = AsmReadDr3 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Dr7 = AsmReadDr7 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Cr4 = AsmReadCr4 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR0 = IMAGE_UNLOAD_SIGNATURE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR2 = The pointer to the ImageContext structure
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR3 = IO_PORT_BREAKPOINT_ADDRESS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // CR4 = Make sure DE(BIT3) is set
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr7 (0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr0 (IMAGE_UNLOAD_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr1 ((UINTN)ImageContext->PdbPointer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr2 ((UINTN)ImageContext);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr7 (0x20000480);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteCr4 (Cr4 | BIT3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // returns a read value other than DEBUG_AGENT_IMAGE_WAIT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generate a software break point.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CpuBreakpoint ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Restore Debug Register State only when Host didn't change it inside exception handler.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // E.g.: User halts the target and sets the HW breakpoint while target is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in the above exception handler
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewDr7 = AsmReadDr7 ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDrxEnabled (0, NewDr7)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr0 (Dr0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDrxEnabled (1, NewDr7)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr1 (Dr1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDrxEnabled (2, NewDr7)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr2 (Dr2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!IsDrxEnabled (3, NewDr7)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr3 (Dr3);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AsmReadCr4 () == (Cr4 | BIT3)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteCr4 (Cr4);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NewDr7 == 0x20000480) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteDr7 (Dr7);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Restore the interrupt state
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetInterruptState (InterruptState);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}