mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-11-04 05:25:45 +01:00 
			
		
		
		
	https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
		
			
				
	
	
		
			225 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  PE/Coff Extra Action library instances.
 | 
						|
 | 
						|
  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <PeCoffExtraActionLib.h>
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the hardware breakpoint in Drx is enabled by checking the Lx and Gx bit in Dr7.
 | 
						|
 | 
						|
  It assumes that DebugAgent will set both Lx and Gx bit when setting up the hardware breakpoint.
 | 
						|
 | 
						|
 | 
						|
  @param  RegisterIndex  Index of Dr register. The value range is from 0 to 3.
 | 
						|
  @param  Dr7            Value of Dr7 register.
 | 
						|
 | 
						|
  @return TRUE   The hardware breakpoint specified in the Drx is enabled.
 | 
						|
  @return FALSE  The hardware breakpoint specified in the Drx is disabled.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsDrxEnabled (
 | 
						|
  IN  UINT8  RegisterIndex,
 | 
						|
  IN  UINTN  Dr7
 | 
						|
  )
 | 
						|
{
 | 
						|
  return (BOOLEAN) (((Dr7 >> (RegisterIndex * 2)) & (BIT0 | BIT1)) == (BIT0 | BIT1));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Common routine to report the PE/COFF image loading/relocating or unloading event.
 | 
						|
 | 
						|
  If ImageContext is NULL, then ASSERT().
 | 
						|
 | 
						|
  @param  ImageContext  Pointer to the image context structure that describes the
 | 
						|
                        PE/COFF image.
 | 
						|
  @param  Signature     IMAGE_LOAD_SIGNATURE or IMAGE_UNLOAD_SIGNATURE.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PeCoffLoaderExtraActionCommon (
 | 
						|
  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,
 | 
						|
  IN     UINTN                         Signature
 | 
						|
  )
 | 
						|
{
 | 
						|
  BOOLEAN                    InterruptState;
 | 
						|
  UINTN                      Dr0;
 | 
						|
  UINTN                      Dr1;
 | 
						|
  UINTN                      Dr2;
 | 
						|
  UINTN                      Dr3;
 | 
						|
  UINTN                      Dr7;
 | 
						|
  UINTN                      Cr4;
 | 
						|
  UINTN                      NewDr7;
 | 
						|
  UINT8                      LoadImageMethod;
 | 
						|
  UINT8                      DebugAgentStatus;
 | 
						|
  IA32_DESCRIPTOR            IdtDescriptor;
 | 
						|
  IA32_IDT_GATE_DESCRIPTOR   OriginalIdtEntry;
 | 
						|
  BOOLEAN                    IdtEntryHooked;
 | 
						|
  UINT32                     RegEdx;
 | 
						|
 | 
						|
  ASSERT (ImageContext != NULL);
 | 
						|
 | 
						|
  if (ImageContext->PdbPointer != NULL) {
 | 
						|
    DEBUG((EFI_D_ERROR, "    PDB = %a\n", ImageContext->PdbPointer));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Disable interrupts and save the current interrupt state
 | 
						|
  //
 | 
						|
  InterruptState = SaveAndDisableInterrupts ();
 | 
						|
 | 
						|
  IdtEntryHooked  = FALSE;
 | 
						|
  LoadImageMethod = PcdGet8 (PcdDebugLoadImageMethod);
 | 
						|
  if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
 | 
						|
    //
 | 
						|
    // If the CPU does not support Debug Extensions(CPUID:01 EDX:BIT2)
 | 
						|
    // then force use of DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3
 | 
						|
    //
 | 
						|
    AsmCpuid (1, NULL, NULL, NULL, &RegEdx);
 | 
						|
    if ((RegEdx & BIT2) == 0) {
 | 
						|
      LoadImageMethod = DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  AsmReadIdtr (&IdtDescriptor);
 | 
						|
  if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
 | 
						|
    if (!CheckDebugAgentHandler (&IdtDescriptor, SOFT_INT_VECTOR_NUM)) {
 | 
						|
      //
 | 
						|
      // Do not trigger INT3 if Debug Agent did not setup IDT entries.
 | 
						|
      //
 | 
						|
      return;
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    if (!CheckDebugAgentHandler (&IdtDescriptor, IO_HW_BREAKPOINT_VECTOR_NUM)) {
 | 
						|
      //
 | 
						|
      // Save and update IDT entry for INT1
 | 
						|
      //
 | 
						|
      SaveAndUpdateIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
 | 
						|
      IdtEntryHooked = TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Save Debug Register State
 | 
						|
  //
 | 
						|
  Dr0 = AsmReadDr0 ();
 | 
						|
  Dr1 = AsmReadDr1 ();
 | 
						|
  Dr2 = AsmReadDr2 ();
 | 
						|
  Dr3 = AsmReadDr3 ();
 | 
						|
  Dr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
 | 
						|
  Cr4 = AsmReadCr4 ();
 | 
						|
 | 
						|
  //
 | 
						|
  // DR0 = Signature
 | 
						|
  // DR1 = The address of the Null-terminated ASCII string for the PE/COFF image's PDB file name
 | 
						|
  // DR2 = The pointer to the ImageContext structure
 | 
						|
  // DR3 = IO_PORT_BREAKPOINT_ADDRESS
 | 
						|
  // DR7 = Disables all HW breakpoints except for DR3 I/O port access of length 1 byte
 | 
						|
  // CR4 = Make sure DE(BIT3) is set
 | 
						|
  //
 | 
						|
  AsmWriteDr7 (BIT10);
 | 
						|
  AsmWriteDr0 (Signature);
 | 
						|
  AsmWriteDr1 ((UINTN) ImageContext->PdbPointer);
 | 
						|
  AsmWriteDr2 ((UINTN) ImageContext);
 | 
						|
  AsmWriteDr3 (IO_PORT_BREAKPOINT_ADDRESS);
 | 
						|
 | 
						|
  if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
 | 
						|
    AsmWriteDr7 (0x20000480);
 | 
						|
    AsmWriteCr4 (Cr4 | BIT3);
 | 
						|
    //
 | 
						|
    // Do an IN from IO_PORT_BREAKPOINT_ADDRESS to generate a HW breakpoint until the port
 | 
						|
    // returns a read value other than DEBUG_AGENT_IMAGE_WAIT
 | 
						|
    //
 | 
						|
    do {
 | 
						|
      DebugAgentStatus = IoRead8 (IO_PORT_BREAKPOINT_ADDRESS);
 | 
						|
    } while (DebugAgentStatus == DEBUG_AGENT_IMAGE_WAIT);
 | 
						|
 | 
						|
  } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
 | 
						|
    //
 | 
						|
    // Generate a software break point.
 | 
						|
    //
 | 
						|
    CpuBreakpoint ();
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Restore Debug Register State only when Host didn't change it inside exception handler.
 | 
						|
  // E.g.: User halts the target and sets the HW breakpoint while target is
 | 
						|
  //       in the above exception handler
 | 
						|
  //
 | 
						|
  NewDr7 = AsmReadDr7 () | BIT10; // H/w sets bit 10, some simulators don't
 | 
						|
  if (!IsDrxEnabled (0, NewDr7) && (AsmReadDr0 () == 0 || AsmReadDr0 () == Signature)) {
 | 
						|
    //
 | 
						|
    // If user changed Dr3 (by setting HW bp in the above exception handler,
 | 
						|
    // we will not set Dr0 to 0 in GO/STEP handler because the break cause is not IMAGE_LOAD/_UNLOAD.
 | 
						|
    //
 | 
						|
    AsmWriteDr0 (Dr0);
 | 
						|
  }
 | 
						|
  if (!IsDrxEnabled (1, NewDr7) && (AsmReadDr1 () == (UINTN) ImageContext->PdbPointer)) {
 | 
						|
    AsmWriteDr1 (Dr1);
 | 
						|
  }
 | 
						|
  if (!IsDrxEnabled (2, NewDr7) && (AsmReadDr2 () == (UINTN) ImageContext)) {
 | 
						|
    AsmWriteDr2 (Dr2);
 | 
						|
  }
 | 
						|
  if (!IsDrxEnabled (3, NewDr7) && (AsmReadDr3 () == IO_PORT_BREAKPOINT_ADDRESS)) {
 | 
						|
    AsmWriteDr3 (Dr3);
 | 
						|
  }
 | 
						|
  if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_IO_HW_BREAKPOINT) {
 | 
						|
    if (AsmReadCr4 () == (Cr4 | BIT3)) {
 | 
						|
      AsmWriteCr4 (Cr4);
 | 
						|
    }
 | 
						|
    if (NewDr7 == 0x20000480) {
 | 
						|
      AsmWriteDr7 (Dr7);
 | 
						|
    }
 | 
						|
  } else if (LoadImageMethod == DEBUG_LOAD_IMAGE_METHOD_SOFT_INT3) {
 | 
						|
    if (NewDr7 == BIT10) {
 | 
						|
      AsmWriteDr7 (Dr7);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Restore original IDT entry for INT1 if it was hooked.
 | 
						|
  //
 | 
						|
  if (IdtEntryHooked) {
 | 
						|
    RestoreIdtEntry1 (&IdtDescriptor, &OriginalIdtEntry);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Restore the interrupt state
 | 
						|
  //
 | 
						|
  SetInterruptState (InterruptState);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Performs additional actions after a PE/COFF image has been loaded and relocated.
 | 
						|
 | 
						|
  @param  ImageContext  Pointer to the image context structure that describes the
 | 
						|
                        PE/COFF image that has already been loaded and relocated.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PeCoffLoaderRelocateImageExtraAction (
 | 
						|
  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_LOAD_SIGNATURE);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Performs additional actions just before a PE/COFF image is unloaded.  Any resources
 | 
						|
  that were allocated by PeCoffLoaderRelocateImageExtraAction() must be freed.
 | 
						|
 | 
						|
  @param  ImageContext  Pointer to the image context structure that describes the
 | 
						|
                        PE/COFF image that is being unloaded.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PeCoffLoaderUnloadImageExtraAction (
 | 
						|
  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext
 | 
						|
  )
 | 
						|
{
 | 
						|
  PeCoffLoaderExtraActionCommon (ImageContext, IMAGE_UNLOAD_SIGNATURE);
 | 
						|
}
 |