From eb0e798d5eb9a88efeb3b1990fa406e85e2da8f6 Mon Sep 17 00:00:00 2001 From: Chris Fernald Date: Tue, 14 Apr 2026 11:53:41 -0700 Subject: [PATCH 1/3] Remove support for AArch64 Visual Studio Build This commit removes the masm assembly and pipeline for visual studio compiled aarch64. This should be built with either GCC or CLANGPDB. --- .azurepipelines/Windows-VS.yml | 2 +- .../Library/DebugAgent/AARCH64/Registers.masm | 201 ------------------ .../Library/DebugAgent/DebugAgentDxe.inf | 1 - .../Library/DebugAgent/DebugAgentMm.inf | 1 - 4 files changed, 1 insertion(+), 204 deletions(-) delete mode 100644 DebuggerFeaturePkg/Library/DebugAgent/AARCH64/Registers.masm diff --git a/.azurepipelines/Windows-VS.yml b/.azurepipelines/Windows-VS.yml index 81de35d..8b23a99 100644 --- a/.azurepipelines/Windows-VS.yml +++ b/.azurepipelines/Windows-VS.yml @@ -12,7 +12,7 @@ ## variables: -- group: architectures-arm64-x86-64 +- group: architectures-x86-64 - group: tool-chain-windows-visual-studio-latest - group: coverage diff --git a/DebuggerFeaturePkg/Library/DebugAgent/AARCH64/Registers.masm b/DebuggerFeaturePkg/Library/DebugAgent/AARCH64/Registers.masm deleted file mode 100644 index d8e24d2..0000000 --- a/DebuggerFeaturePkg/Library/DebugAgent/AARCH64/Registers.masm +++ /dev/null @@ -1,201 +0,0 @@ -; -; Assembly implementation for accessing ARM registers for MSVC. -; -; Copyright (c) Microsoft Corporation. -; SPDX-License-Identifier: BSD-2-Clause-Patent -; - - AREA |.text|,ALIGN=3,CODE,READONLY - - EXPORT DebugReadMdscrEl1 - EXPORT DebugWriteMdscrEl1 - EXPORT DebugReadOslsrEl1 - EXPORT DebugWriteOslarEl1 - EXPORT DebugReadDaif - EXPORT DebugWriteDaif - EXPORT DebugGetTCR - EXPORT DebugGetTTBR0BaseAddress - EXPORT DebugReadDbgWvr0El1 - EXPORT DebugWriteDbgWvr0El1 - EXPORT DebugReadDbgWcr0El1 - EXPORT DebugWriteDbgWcr0El1 - EXPORT DebugReadDbgWvr1El1 - EXPORT DebugWriteDbgWvr1El1 - EXPORT DebugReadDbgWcr1El1 - EXPORT DebugWriteDbgWcr1El1 - EXPORT DebugReadDbgWvr2El1 - EXPORT DebugWriteDbgWvr2El1 - EXPORT DebugReadDbgWcr2El1 - EXPORT DebugWriteDbgWcr2El1 - EXPORT DebugReadDbgWvr3El1 - EXPORT DebugWriteDbgWvr3El1 - EXPORT DebugReadDbgWcr3El1 - EXPORT DebugWriteDbgWcr3El1 - - -DebugReadMdscrEl1 PROC - mrs x0, mdscr_el1 - ret -DebugReadMdscrEl1 ENDP - - -DebugWriteMdscrEl1 PROC - msr mdscr_el1, x0 - ret -DebugWriteMdscrEl1 ENDP - - -DebugReadOslsrEl1 PROC - mrs x0, oslsr_el1 - ret -DebugReadOslsrEl1 ENDP - - -DebugWriteOslarEl1 PROC - msr oslar_el1, x0 - ret -DebugWriteOslarEl1 ENDP - - -DebugReadDaif PROC - mrs x0, daif - ret -DebugReadDaif ENDP - - -DebugWriteDaif PROC - msr daif, x0 - ret -DebugWriteDaif ENDP - - -DebugGetTCR PROC - mrs x1, CurrentEL - cmp x1, #0x8 - b.lt %f1 - b %f2 -1 - mrs x0, tcr_el1 - b %f3 -2 - mrs x0, tcr_el2 -3 - isb sy - ret -ArmGetTCR ENDP - - -DebugGetTTBR0BaseAddress PROC - mrs x1, CurrentEL - cmp x1, #0x8 - b.lt %f1 - b %f2 -1 - mrs x0, ttbr0_el1 - b %f3 -2 - mrs x0, ttbr0_el2 -3 - ldr x1, =0xFFFFFFFFFFFF - and x0, x0, x1 - isb sy - ret -ArmGetTTBR0BaseAddress ENDP - -DebugReadDbgWvr0El1 PROC - mrs x0, dbgwvr0_el1 - ret -DebugReadDbgWvr0El1 ENDP - - -DebugWriteDbgWvr0El1 PROC - msr dbgwvr0_el1, x0 - ret -DebugWriteDbgWvr0El1 ENDP - - -DebugReadDbgWcr0El1 PROC - mrs x0, dbgwcr0_el1 - ret -DebugReadDbgWcr0El1 ENDP - - -DebugWriteDbgWcr0El1 PROC - msr dbgwcr0_el1, x0 - ret -DebugWriteDbgWcr0El1 ENDP - - -DebugReadDbgWvr1El1 PROC - mrs x0, dbgwvr1_el1 - ret -DebugReadDbgWvr1El1 ENDP - - -DebugWriteDbgWvr1El1 PROC - msr dbgwvr1_el1, x0 - ret -DebugWriteDbgWvr1El1 ENDP - - -DebugReadDbgWcr1El1 PROC - mrs x0, dbgwcr1_el1 - ret -DebugReadDbgWcr1El1 ENDP - - -DebugWriteDbgWcr1El1 PROC - msr dbgwcr1_el1, x0 - ret -DebugWriteDbgWcr1El1 ENDP - - -DebugReadDbgWvr2El1 PROC - mrs x0, dbgwvr2_el1 - ret -DebugReadDbgWvr2El1 ENDP - - -DebugWriteDbgWvr2El1 PROC - msr dbgwvr2_el1, x0 - ret -DebugWriteDbgWvr2El1 ENDP - - -DebugReadDbgWcr2El1 PROC - mrs x0, dbgwcr2_el1 - ret -DebugReadDbgWcr2El1 ENDP - - -DebugWriteDbgWcr2El1 PROC - msr dbgwcr2_el1, x0 - ret -DebugWriteDbgWcr2El1 ENDP - - -DebugReadDbgWvr3El1 PROC - mrs x0, dbgwvr3_el1 - ret -DebugReadDbgWvr3El1 ENDP - - -DebugWriteDbgWvr3El1 PROC - msr dbgwvr3_el1, x0 - ret -DebugWriteDbgWvr3El1 ENDP - - -DebugReadDbgWcr3El1 PROC - mrs x0, dbgwcr3_el1 - ret -DebugReadDbgWcr3El1 ENDP - - -DebugWriteDbgWcr3El1 PROC - msr dbgwcr3_el1, x0 - ret -DebugWriteDbgWcr3El1 ENDP - - - END diff --git a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.inf b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.inf index faefcb9..855be57 100644 --- a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.inf +++ b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.inf @@ -31,7 +31,6 @@ [Sources.AARCH64] AARCH64/DebugAarch64.c - AARCH64/Registers.masm | MSFT AARCH64/Registers.S | GCC AARCH64/Registers.h GdbStub/GdbStubAarch64.c diff --git a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentMm.inf b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentMm.inf index c4ded05..fe0d728 100644 --- a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentMm.inf +++ b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentMm.inf @@ -32,7 +32,6 @@ [Sources.AARCH64] AARCH64/DebugAarch64.c - AARCH64/Registers.masm | MSFT AARCH64/Registers.S | GCC GdbStub/GdbStubAarch64.c From b2276a73e703c612c8ba2e930323fffdc1d07710 Mon Sep 17 00:00:00 2001 From: Chris Fernald Date: Tue, 14 Apr 2026 12:10:18 -0700 Subject: [PATCH 2/3] Cleanup style and convention issues This commit cleans up several style and convention issues in DebuggerFeaturePkg. --- .../Library/DebugAgent/AARCH64/DebugAarch64.c | 16 +++---- .../Library/DebugAgent/Breakpoint.c | 18 +++---- .../Library/DebugAgent/DebugAgent.h | 30 ++++++------ .../Library/DebugAgent/DebugAgentDxe.c | 48 +++++++++---------- .../Library/DebugAgent/DebugAgentMm.c | 36 +++++++------- .../Library/DebugAgent/Readme.md | 6 +++ .../Library/DebugAgent/X64/DebugX64.c | 12 ++--- 7 files changed, 84 insertions(+), 82 deletions(-) diff --git a/DebuggerFeaturePkg/Library/DebugAgent/AARCH64/DebugAarch64.c b/DebuggerFeaturePkg/Library/DebugAgent/AARCH64/DebugAarch64.c index 8e6a21e..16d2f74 100644 --- a/DebuggerFeaturePkg/Library/DebugAgent/AARCH64/DebugAarch64.c +++ b/DebuggerFeaturePkg/Library/DebugAgent/AARCH64/DebugAarch64.c @@ -6,8 +6,6 @@ **/ -#include -#include #include #include #include @@ -54,10 +52,10 @@ typedef union _DBG_WCR { // Structures used by the arch-agnostic code. // -UINT8 ArchBreakpointInstruction[] = { 0x00, 0x00, 0x3E, 0xD4 }; -UINTN ArchBreakpointInstructionSize = sizeof (ArchBreakpointInstruction); +UINT8 mArchBreakpointInstruction[] = { 0x00, 0x00, 0x3E, 0xD4 }; +UINTN mArchBreakpointInstructionSize = sizeof (mArchBreakpointInstruction); -UINT32 ArchExceptionTypes[] = { +UINT32 mArchExceptionTypes[] = { EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS, MAX_UINT32 // End of list }; @@ -106,8 +104,8 @@ DEBUG_WATCHPOINT_REGISTERS DebugWatchpointRegisters[] = { VOID EFIAPI DebuggerExceptionHandler ( - EFI_EXCEPTION_TYPE InterruptType, - EFI_SYSTEM_CONTEXT SystemContext + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext ) { EFI_SYSTEM_CONTEXT_AARCH64 *Context; @@ -194,9 +192,9 @@ DebuggerExceptionHandler ( // if ((ExceptionType == 0x3c) && - (CompareMem ((UINT8 *)Context->ELR, &ArchBreakpointInstruction[0], ArchBreakpointInstructionSize) == 0)) + (CompareMem ((UINT8 *)Context->ELR, &mArchBreakpointInstruction[0], mArchBreakpointInstructionSize) == 0)) { - Context->ELR += ArchBreakpointInstructionSize; + Context->ELR += mArchBreakpointInstructionSize; } // diff --git a/DebuggerFeaturePkg/Library/DebugAgent/Breakpoint.c b/DebuggerFeaturePkg/Library/DebugAgent/Breakpoint.c index d797bb0..0a4c0c8 100644 --- a/DebuggerFeaturePkg/Library/DebugAgent/Breakpoint.c +++ b/DebuggerFeaturePkg/Library/DebugAgent/Breakpoint.c @@ -37,14 +37,14 @@ BREAKPOINT_REASON DebuggerBreakpointReason = BreakpointReasonNone; **/ BOOLEAN AddSoftwareBreakpoint ( - UINTN Address + IN UINTN Address ) { UINTN i; BREAKPOINT_INFO *Entry; // Make sure we don't overflow OriginalValue. - ASSERT (ArchBreakpointInstructionSize <= MAX_BREAKPOINT_SIZE); + ASSERT (mArchBreakpointInstructionSize <= MAX_BREAKPOINT_SIZE); Entry = NULL; for (i = 0; i < MAX_BREAKPOINTS; i++) { @@ -65,9 +65,9 @@ AddSoftwareBreakpoint ( Entry->Active = TRUE; Entry->Address = Address; - DbgReadMemory (Address, &(Entry->OriginalValue[0]), ArchBreakpointInstructionSize); - DbgWriteMemory (Address, ArchBreakpointInstruction, ArchBreakpointInstructionSize); - InvalidateInstructionCacheRange ((VOID *)Address, ArchBreakpointInstructionSize); + DbgReadMemory (Address, &(Entry->OriginalValue[0]), mArchBreakpointInstructionSize); + DbgWriteMemory (Address, mArchBreakpointInstruction, mArchBreakpointInstructionSize); + InvalidateInstructionCacheRange ((VOID *)Address, mArchBreakpointInstructionSize); return TRUE; } @@ -81,16 +81,16 @@ AddSoftwareBreakpoint ( **/ BOOLEAN RemoveSoftwareBreakpoint ( - UINTN Address + IN UINTN Address ) { UINTN i; for (i = 0; i < MAX_BREAKPOINTS; i++) { if (mBreakpoints[i].Active && (mBreakpoints[i].Address == Address)) { - DbgWriteMemory (Address, &(mBreakpoints[i].OriginalValue[0]), ArchBreakpointInstructionSize); + DbgWriteMemory (Address, &(mBreakpoints[i].OriginalValue[0]), mArchBreakpointInstructionSize); mBreakpoints[i].Active = FALSE; - InvalidateInstructionCacheRange ((VOID *)Address, ArchBreakpointInstructionSize); + InvalidateInstructionCacheRange ((VOID *)Address, mArchBreakpointInstructionSize); return TRUE; } } @@ -107,7 +107,7 @@ RemoveSoftwareBreakpoint ( **/ VOID DebuggerBreak ( - BREAKPOINT_REASON Reason + IN BREAKPOINT_REASON Reason ) { DebuggerBreakpointReason = Reason; diff --git a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgent.h b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgent.h index eceddd7..8a2d23d 100644 --- a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgent.h +++ b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgent.h @@ -67,9 +67,9 @@ typedef struct _EXCEPTION_INFO { // Architecture specific definitions used by general debugger code. // -extern UINT8 ArchBreakpointInstruction[]; -extern UINTN ArchBreakpointInstructionSize; -extern UINT32 ArchExceptionTypes[]; +extern UINT8 mArchBreakpointInstruction[]; +extern UINTN mArchBreakpointInstructionSize; +extern UINT32 mArchExceptionTypes[]; // // Global used to track debugger invoked breakpoint. @@ -93,8 +93,8 @@ extern CONST CHAR8 *gDebuggerInfo; VOID EFIAPI DebuggerExceptionHandler ( - EFI_EXCEPTION_TYPE InterruptType, - EFI_SYSTEM_CONTEXT SystemContext + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext ); EFI_STATUS @@ -134,16 +134,16 @@ IsPageWritable ( BOOLEAN DbgReadMemory ( - UINTN Address, - VOID *Data, - UINTN Length + IN UINTN Address, + OUT VOID *Data, + IN UINTN Length ); BOOLEAN DbgWriteMemory ( - UINTN Address, - VOID *Data, - UINTN Length + IN UINTN Address, + IN VOID *Data, + IN UINTN Length ); // @@ -163,7 +163,7 @@ DebuggerPollInput ( VOID DebuggerInitialBreakpoint ( - UINT64 Timeout + IN UINT64 Timeout ); // @@ -172,17 +172,17 @@ DebuggerInitialBreakpoint ( BOOLEAN AddSoftwareBreakpoint ( - UINTN Address + IN UINTN Address ); BOOLEAN RemoveSoftwareBreakpoint ( - UINTN Address + IN UINTN Address ); VOID DebuggerBreak ( - BREAKPOINT_REASON Reason + IN BREAKPOINT_REASON Reason ); // diff --git a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.c b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.c index 67d0eb3..2eb9c89 100644 --- a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.c +++ b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.c @@ -275,7 +275,7 @@ OnLoadedImageNotification ( CHAR8 *PdbPointer; CHAR8 Name[64]; CHAR8 *NameEnd; - UINTN i; + UINTN Index; BufferSize = sizeof (EFI_HANDLE); @@ -314,9 +314,9 @@ OnLoadedImageNotification ( } // Strip of the directories. - for (i = AsciiStrLen (PdbPointer); i > 0; i--) { - if ((PdbPointer[i - 1] == '\\') || (PdbPointer[i - 1] == '/')) { - PdbPointer = &PdbPointer[i]; + for (Index = AsciiStrLen (PdbPointer); Index > 0; Index--) { + if ((PdbPointer[Index - 1] == '\\') || (PdbPointer[Index - 1] == '/')) { + PdbPointer = &PdbPointer[Index]; break; } } @@ -347,18 +347,18 @@ VOID DebugAgentExceptionDestroy ( ) { - UINT8 i; + UINT8 Index; if (gCpu != NULL) { - for (i = 0; ArchExceptionTypes[i] != MAX_UINT32; i += 1) { + for (Index = 0; mArchExceptionTypes[Index] != MAX_UINT32; Index += 1) { if (gCpu != NULL) { gCpu->RegisterInterruptHandler ( gCpu, - ArchExceptionTypes[i], + mArchExceptionTypes[Index], NULL ); } else { - RegisterCpuInterruptHandler (ArchExceptionTypes[i], NULL); + RegisterCpuInterruptHandler (mArchExceptionTypes[Index], NULL); } } } @@ -375,21 +375,21 @@ EFI_STATUS DebugAgentExceptionInitialize ( ) { - UINT8 i; + UINT8 Index; EFI_STATUS Status; // First uninstall any handler that needs to be replaced. DebugAgentExceptionDestroy (); - for (i = 0; ArchExceptionTypes[i] != MAX_UINT32; i += 1) { + for (Index = 0; mArchExceptionTypes[Index] != MAX_UINT32; Index += 1) { if (gCpu != NULL) { Status = gCpu->RegisterInterruptHandler ( gCpu, - ArchExceptionTypes[i], + mArchExceptionTypes[Index], DebuggerExceptionHandler ); } else { - Status = RegisterCpuInterruptHandler (ArchExceptionTypes[i], DebuggerExceptionHandler); + Status = RegisterCpuInterruptHandler (mArchExceptionTypes[Index], DebuggerExceptionHandler); } if (EFI_ERROR (Status)) { @@ -428,10 +428,10 @@ DebugReboot ( **/ BOOLEAN AccessMemory ( - UINTN Address, - UINT8 *Data, - UINTN Length, - BOOLEAN Write + IN UINTN Address, + IN OUT UINT8 *Data, + IN UINTN Length, + IN BOOLEAN Write ) { UINTN LengthInPage; @@ -517,7 +517,7 @@ AccessMemory ( Read system memory. @param[in] Address The virtual address of the memory access. - @param[in,out] Data The buffer to read memory into. + @param[out] Data The buffer to read memory into. @param[in] Length The length of the memory range. @retval TRUE Memory access was complete successfully. @@ -525,9 +525,9 @@ AccessMemory ( **/ BOOLEAN DbgReadMemory ( - UINTN Address, - VOID *Data, - UINTN Length + IN UINTN Address, + OUT VOID *Data, + IN UINTN Length ) { return AccessMemory (Address, Data, Length, FALSE); @@ -537,7 +537,7 @@ DbgReadMemory ( Write to system memory. @param[in] Address The virtual address of the memory access. - @param[in,out] Data The buffer of data to write. + @param[in] Data The buffer of data to write. @param[in] Length The length of the memory range. @retval TRUE Memory access was complete successfully. @@ -545,9 +545,9 @@ DbgReadMemory ( **/ BOOLEAN DbgWriteMemory ( - UINTN Address, - VOID *Data, - UINTN Length + IN UINTN Address, + IN VOID *Data, + IN UINTN Length ) { return AccessMemory (Address, Data, Length, TRUE); diff --git a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentMm.c b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentMm.c index bab3cfa..11823a0 100644 --- a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentMm.c +++ b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentMm.c @@ -76,10 +76,10 @@ VOID DebugAgentExceptionDestroy ( ) { - UINT8 i; + UINT8 Index; - for (i = 0; ArchExceptionTypes[i] != MAX_UINT32; i += 1) { - RegisterCpuInterruptHandler (ArchExceptionTypes[i], NULL); + for (Index = 0; mArchExceptionTypes[Index] != MAX_UINT32; Index += 1) { + RegisterCpuInterruptHandler (mArchExceptionTypes[Index], NULL); } } @@ -94,14 +94,14 @@ EFI_STATUS DebugAgentExceptionInitialize ( ) { - UINT8 i; + UINT8 Index; EFI_STATUS Status; // First uninstall any handler that needs to be replaced. DebugAgentExceptionDestroy (); - for (i = 0; ArchExceptionTypes[i] != MAX_UINT32; i += 1) { - Status = RegisterCpuInterruptHandler (ArchExceptionTypes[i], DebuggerExceptionHandler); + for (Index = 0; mArchExceptionTypes[Index] != MAX_UINT32; Index += 1) { + Status = RegisterCpuInterruptHandler (mArchExceptionTypes[Index], DebuggerExceptionHandler); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); DebugAgentExceptionDestroy (); @@ -139,10 +139,10 @@ DebugReboot ( **/ BOOLEAN AccessMemory ( - UINTN Address, - UINT8 *Data, - UINTN Length, - BOOLEAN Write + IN UINTN Address, + IN OUT UINT8 *Data, + IN UINTN Length, + IN BOOLEAN Write ) { UINTN LengthInPage; @@ -218,7 +218,7 @@ AccessMemory ( Read system memory. @param[in] Address The virtual address of the memory access. - @param[in,out] Data The buffer to read memory into. + @param[out] Data The buffer to read memory into. @param[in] Length The length of the memory range. @retval TRUE Memory access was complete successfully. @@ -226,9 +226,9 @@ AccessMemory ( **/ BOOLEAN DbgReadMemory ( - UINTN Address, - VOID *Data, - UINTN Length + IN UINTN Address, + OUT VOID *Data, + IN UINTN Length ) { return AccessMemory (Address, Data, Length, FALSE); @@ -238,7 +238,7 @@ DbgReadMemory ( Write to system memory. @param[in] Address The virtual address of the memory access. - @param[in,out] Data The buffer of data to write. + @param[in] Data The buffer of data to write. @param[in] Length The length of the memory range. @retval TRUE Memory access was complete successfully. @@ -246,9 +246,9 @@ DbgReadMemory ( **/ BOOLEAN DbgWriteMemory ( - UINTN Address, - VOID *Data, - UINTN Length + IN UINTN Address, + IN VOID *Data, + IN UINTN Length ) { return AccessMemory (Address, Data, Length, TRUE); diff --git a/DebuggerFeaturePkg/Library/DebugAgent/Readme.md b/DebuggerFeaturePkg/Library/DebugAgent/Readme.md index c4d1731..c41f3d7 100644 --- a/DebuggerFeaturePkg/Library/DebugAgent/Readme.md +++ b/DebuggerFeaturePkg/Library/DebugAgent/Readme.md @@ -34,6 +34,12 @@ Currently the only implementation is the [GdbStub](./GdbStub) which also has som architecture specific files to handle accessing architecture specific information like registers. +## MM & PEI Support + +Both the MM and PEI implementations are experimental and purely for development +scenarios. They do not support dynamic configuration and are not as feature rich +as the DXE implementation. + ## Copyright Copyright (C) Microsoft Corporation. All rights reserved. diff --git a/DebuggerFeaturePkg/Library/DebugAgent/X64/DebugX64.c b/DebuggerFeaturePkg/Library/DebugAgent/X64/DebugX64.c index 50dd37a..e349b05 100644 --- a/DebuggerFeaturePkg/Library/DebugAgent/X64/DebugX64.c +++ b/DebuggerFeaturePkg/Library/DebugAgent/X64/DebugX64.c @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include #include @@ -63,10 +61,10 @@ STATIC UINT64 mPerformanceCounterFreq; // Structures used by the arch-agnostic code. // -UINT8 ArchBreakpointInstruction[] = { 0xCC }; -UINTN ArchBreakpointInstructionSize = sizeof (ArchBreakpointInstruction); +UINT8 mArchBreakpointInstruction[] = { 0xCC }; +UINTN mArchBreakpointInstructionSize = sizeof (mArchBreakpointInstruction); -UINT32 ArchExceptionTypes[] = { +UINT32 mArchExceptionTypes[] = { EXCEPT_X64_DIVIDE_ERROR, EXCEPT_X64_DEBUG, EXCEPT_X64_BREAKPOINT, @@ -92,8 +90,8 @@ UINT32 ArchExceptionTypes[] = { VOID EFIAPI DebuggerExceptionHandler ( - EFI_EXCEPTION_TYPE InterruptType, - EFI_SYSTEM_CONTEXT SystemContext + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext ) { EFI_SYSTEM_CONTEXT_X64 *Context; From 90cd641b8c23d3c9c912b3ce3104d1a5669b556d Mon Sep 17 00:00:00 2001 From: Chris Fernald Date: Tue, 14 Apr 2026 12:11:02 -0700 Subject: [PATCH 3/3] Implement PEI debug agent This commit implements a PEI debug agent that supports post-memory environments. Because the PEI core doesn't have proper debug agent support, this also introduces a simple PEIM that initialized the debug agent. This PEIM has will only be dispatched when memory is discovered. --- .../DebugAgentPei/DebugAgentPei.c | 34 +++ .../DebugAgentPei/DebugAgentPei.inf | 38 +++ DebuggerFeaturePkg/DebuggerFeaturePkg.dec | 4 + DebuggerFeaturePkg/DebuggerFeaturePkg.dsc | 12 + .../Library/DebugAgent/DebugAgentPeiLib.c | 248 ++++++++++++++++++ .../Library/DebugAgent/DebugAgentPeiLib.inf | 67 +++++ 6 files changed, 403 insertions(+) create mode 100644 DebuggerFeaturePkg/DebugAgentPei/DebugAgentPei.c create mode 100644 DebuggerFeaturePkg/DebugAgentPei/DebugAgentPei.inf create mode 100644 DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.c create mode 100644 DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.inf diff --git a/DebuggerFeaturePkg/DebugAgentPei/DebugAgentPei.c b/DebuggerFeaturePkg/DebugAgentPei/DebugAgentPei.c new file mode 100644 index 0000000..754d5d5 --- /dev/null +++ b/DebuggerFeaturePkg/DebugAgentPei/DebugAgentPei.c @@ -0,0 +1,34 @@ +/** @file + Thin PEIM wrapper that invokes the PEI debug agent library. + + This PEIM is dispatched after permanent memory is available (DEPEX on + gEfiPeiMemoryDiscoveredPpiGuid). It simply calls InitializeDebugAgent + to let the library perform all initialization. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/** + PEIM entry point. Invokes the debug agent library initialization. + + @param[in] FileHandle Handle of the file being loaded. + @param[in] PeiServices Pointer to PEI Services table. + + @retval EFI_SUCCESS Debug agent initialized successfully. + +**/ +EFI_STATUS +EFIAPI +DebugAgentPeiEntry ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + InitializeDebugAgent (DEBUG_AGENT_INIT_PEI, NULL, NULL); + return EFI_SUCCESS; +} diff --git a/DebuggerFeaturePkg/DebugAgentPei/DebugAgentPei.inf b/DebuggerFeaturePkg/DebugAgentPei/DebugAgentPei.inf new file mode 100644 index 0000000..f147567 --- /dev/null +++ b/DebuggerFeaturePkg/DebugAgentPei/DebugAgentPei.inf @@ -0,0 +1,38 @@ +## @file +# +# Thin PEIM wrapper for the PEI debug agent. All logic lives in +# DebugAgentLib (PeiDebugAgentLib). This PEIM is dispatched after +# permanent memory is installed. +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + +[Defines] + INF_VERSION = 1.27 + BASE_NAME = DebugAgentPei + FILE_GUID = 7A4F8B72-E12D-4A62-B5C4-D43F89735E28 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = DebugAgentPeiEntry + +[Sources] + DebugAgentPei.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DebuggerFeaturePkg/DebuggerFeaturePkg.dec + +[LibraryClasses] + PeimEntryPoint + DebugAgentLib + PrintLib + +[Ppis] + gEfiPeiMemoryDiscoveredPpiGuid ## CONSUMES + +[Depex] + gEfiPeiMemoryDiscoveredPpiGuid diff --git a/DebuggerFeaturePkg/DebuggerFeaturePkg.dec b/DebuggerFeaturePkg/DebuggerFeaturePkg.dec index b1280d1..4cc07de 100644 --- a/DebuggerFeaturePkg/DebuggerFeaturePkg.dec +++ b/DebuggerFeaturePkg/DebuggerFeaturePkg.dec @@ -54,6 +54,10 @@ # phase implementation. DebuggerFeaturePkgTokenSpaceGuid.PcdForceEnableDebugger|FALSE|BOOLEAN|0x00000003 + ## Forcibly enables the PEI debugger. This is the only way to enable the PEI + # phase debugger. No HOB or dynamic configuration is supported for PEI. + DebuggerFeaturePkgTokenSpaceGuid.PcdForceEnablePeiDebugger|FALSE|BOOLEAN|0x00000005 + ## Enabled work-arounds in the debugger for bugs in windbg's GDB implementation. # This should not break GDB debuggers, but may cause slightly unexpected behavior. DebuggerFeaturePkgTokenSpaceGuid.PcdEnableWindbgWorkarounds|TRUE|BOOLEAN|0x00000004 diff --git a/DebuggerFeaturePkg/DebuggerFeaturePkg.dsc b/DebuggerFeaturePkg/DebuggerFeaturePkg.dsc index 0d90c53..3c600b3 100644 --- a/DebuggerFeaturePkg/DebuggerFeaturePkg.dsc +++ b/DebuggerFeaturePkg/DebuggerFeaturePkg.dsc @@ -38,6 +38,13 @@ WatchdogTimerLib|DebuggerFeaturePkg/Library/WatchdogTimerLibNull/WatchdogTimerLibNull.inf TransportLogControlLib|DebuggerFeaturePkg/Library/TransportLogControlLibNull/TransportLogControlLibNull.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf + CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + HwResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf + StackCheckLib|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf [LibraryClasses.common.PEIM] @@ -54,3 +61,8 @@ [Components.X64, Components.AARCH64] DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.inf DebuggerFeaturePkg/Library/DebugAgent/DebugAgentMm.inf + DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.inf + DebuggerFeaturePkg/DebugAgentPei/DebugAgentPei.inf { + + DebugAgentLib|DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.inf + } diff --git a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.c b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.c new file mode 100644 index 0000000..ea05cf5 --- /dev/null +++ b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.c @@ -0,0 +1,248 @@ +/** @file DebugAgentPeiLib.c + + Implementation of the DebugAgentLib for PEI phase (post-memory only). + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "DebugAgent.h" + +CONST CHAR8 *gDebuggerInfo = "PEI UEFI Debugger"; + +// +// Default PEI debug configuration. No timeout, initial breakpoint enabled. +// + +DEBUGGER_CONTROL_HOB DefaultPeiDebugConfig = { + .Control.AsUint32 = 0x1, // InitialBreakpoint only + .PerformanceCounterFreq = 0x300000, // Reasonable guess, timing may be inaccurate. + .InitialBreakpointTimeout = 0 // No timeout +}; + +// +// Debug log buffers +// + +#ifdef DBG_DEBUG +CHAR8 DbgLogBuffer[DBG_LOG_SIZE]; +UINTN DbgLogOffset = 0; +#endif + +/** + This routine removes the exception handling support. + +**/ +VOID +DebugAgentExceptionDestroy ( + ) +{ + UINT8 Index; + + for (Index = 0; mArchExceptionTypes[Index] != MAX_UINT32; Index += 1) { + RegisterCpuInterruptHandler (mArchExceptionTypes[Index], NULL); + } +} + +/** + This routine initializes the debugger exception handling support. + + @retval EFI_SUCCESS On success. + @retval EFI_STATUS On failure. + +**/ +EFI_STATUS +DebugAgentExceptionInitialize ( + ) +{ + UINT8 Index; + EFI_STATUS Status; + + Status = InitializeCpuExceptionHandlers (NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: InitializeCpuExceptionHandlers failed - %r\n", __func__, Status)); + return Status; + } + + for (Index = 0; mArchExceptionTypes[Index] != MAX_UINT32; Index += 1) { + Status = RegisterCpuInterruptHandler (mArchExceptionTypes[Index], DebuggerExceptionHandler); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + DebugAgentExceptionDestroy (); + return Status; + } + } + + return Status; +} + +/** + Reboots the system. + +**/ +VOID +DebugReboot ( + VOID + ) +{ + // NOT IMPLEMENTED for PEI. + return; +} + +/** + Read system memory. In PEI post-mem, all memory is directly accessible. + + @param[in] Address The virtual address of the memory access. + @param[out] Data The buffer to read memory into. + @param[in] Length The length of the memory range. + + @retval TRUE Memory access was complete successfully. + @retval FALSE Memory access failed, either completely or partially. +**/ +BOOLEAN +DbgReadMemory ( + IN UINTN Address, + OUT VOID *Data, + IN UINTN Length + ) +{ + if (!IsPageReadable (Address)) { + return FALSE; + } + + CopyMem (Data, (VOID *)Address, Length); + return TRUE; +} + +/** + Write to system memory. In PEI post-mem, all memory is directly accessible. + + @param[in] Address The virtual address of the memory access. + @param[in] Data The buffer of data to write. + @param[in] Length The length of the memory range. + + @retval TRUE Memory access was complete successfully. + @retval FALSE Memory access failed, either completely or partially. +**/ +BOOLEAN +DbgWriteMemory ( + IN UINTN Address, + IN VOID *Data, + IN UINTN Length + ) +{ + if (!IsPageWritable (Address)) { + return FALSE; + } + + CopyMem ((VOID *)Address, Data, Length); + return TRUE; +} + +/** + Setup the debugger to break when a particular module is loaded. + + @param[in] Module The name of the module. + + @retval TRUE The break on module was set. + @retval FALSE The break on module was not set. + +**/ +BOOLEAN +DbgSetBreakOnModuleLoad ( + IN CHAR8 *Module + ) +{ + // NOT SUPPORTED in PEI. + return FALSE; +} + +/** + Initialize debug agent. + + When called with DEBUG_AGENT_INIT_PEI, performs the full PEI debug agent + initialization: transport, architecture-specific setup, exception handlers, + and initial breakpoint. + + @param[in] InitFlag Init flag. DEBUG_AGENT_INIT_PEI to initialize. + @param[in] Context Context needed according to InitFlag; it was optional. + @param[in] Function Continue function called by debug agent library; it was + optional. + +**/ +VOID +EFIAPI +InitializeDebugAgent ( + IN UINT32 InitFlag, + IN VOID *Context OPTIONAL, + IN DEBUG_AGENT_CONTINUE Function OPTIONAL + ) +{ + EFI_STATUS Status; + + if (!PcdGetBool (PcdForceEnablePeiDebugger)) { + DEBUG ((DEBUG_INFO, "%a: PEI debugger not enabled.\n", __func__)); + return; + } + + Status = DebugTransportInitialize (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Transport init failed - %r\n", __func__, Status)); + return; + } + + DebugArchInit (&DefaultPeiDebugConfig); + + Status = DebugAgentExceptionInitialize (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Exception init failed - %r\n", __func__, Status)); + return; + } + + DEBUG ((DEBUG_INFO, "%a: PEI debug agent initialized.\n", __func__)); + + // + // Always perform an initial breakpoint with no timeout for PEI. + // + DebuggerInitialBreakpoint (0); +} + +/** + Enable/Disable the interrupt of debug timer and return the interrupt state + prior to the operation. + + If EnableStatus is TRUE, enable the interrupt of debug timer. + If EnableStatus is FALSE, disable the interrupt of debug timer. + + @param[in] EnableStatus Enable/Disable. + + @return FALSE always. + +**/ +BOOLEAN +EFIAPI +SaveAndSetDebugTimerInterrupt ( + IN BOOLEAN EnableStatus + ) +{ + return FALSE; +} diff --git a/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.inf b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.inf new file mode 100644 index 0000000..e84682b --- /dev/null +++ b/DebuggerFeaturePkg/Library/DebugAgent/DebugAgentPeiLib.inf @@ -0,0 +1,67 @@ +## @file +# +# The PEI implementation of the DebugAgent. +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + +[Defines] + INF_VERSION = 1.27 + BASE_NAME = PeiDebugAgentLib + FILE_GUID = 7A4F8B72-E12D-4A62-B5C4-D43F89735E27 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugAgentLib | PEIM PEI_CORE + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = X64 AARCH64 +# + +[Sources] + DebugAgentPeiLib.c + DebugAgent.h + Breakpoint.c + GdbStub/GdbStub.c + GdbStub/GdbStub.h + +[Sources.AARCH64] + AARCH64/DebugAarch64.c + AARCH64/Registers.S | GCC + AARCH64/Registers.h + GdbStub/GdbStubAarch64.c + +[Sources.X64] + X64/DebugX64.c + X64/AddressCheck.c + X64/VirtualMemory.h + GdbStub/GdbStubX64.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DebuggerFeaturePkg/DebuggerFeaturePkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + HobLib + WatchdogTimerLib + TimerLib + CpuExceptionHandlerLib + CacheMaintenanceLib + DebugTransportLib + TransportLogControlLib + PcdLib + PeiServicesLib + +[Pcd.common] + DebuggerFeaturePkgTokenSpaceGuid.PcdForceEnablePeiDebugger ## CONSUMES + DebuggerFeaturePkgTokenSpaceGuid.PcdEnableWindbgWorkarounds ## CONSUMES + +[BuildOptions] + GCC:*_*_*_CC_FLAGS = -D BUILDING_IN_UEFI