123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972 |
- /** @file
- Processor specific parts of the GDB stub
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <GdbStubInternal.h>
- //
- // Array of exception types that need to be hooked by the debugger
- // {EFI mapping, GDB mapping}
- //
- EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
- { EXCEPT_IA32_DIVIDE_ERROR, GDB_SIGFPE },
- { EXCEPT_IA32_DEBUG, GDB_SIGTRAP },
- { EXCEPT_IA32_NMI, GDB_SIGEMT },
- { EXCEPT_IA32_BREAKPOINT, GDB_SIGTRAP },
- { EXCEPT_IA32_OVERFLOW, GDB_SIGSEGV },
- { EXCEPT_IA32_BOUND, GDB_SIGSEGV },
- { EXCEPT_IA32_INVALID_OPCODE, GDB_SIGILL },
- { EXCEPT_IA32_DOUBLE_FAULT, GDB_SIGEMT },
- { EXCEPT_IA32_STACK_FAULT, GDB_SIGSEGV },
- { EXCEPT_IA32_GP_FAULT, GDB_SIGSEGV },
- { EXCEPT_IA32_PAGE_FAULT, GDB_SIGSEGV },
- { EXCEPT_IA32_FP_ERROR, GDB_SIGEMT },
- { EXCEPT_IA32_ALIGNMENT_CHECK, GDB_SIGEMT },
- { EXCEPT_IA32_MACHINE_CHECK, GDB_SIGEMT }
- };
- // The offsets of registers SystemContext.
- // The fields in the array are in the gdb ordering.
- //
- // 16 regs
- UINTN gRegisterOffsets[] = {
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Eax),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ecx),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Edx),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ebx),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Esp),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ebp),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Esi),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Edi),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Eip),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Eflags),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Cs),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ss),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ds),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Es),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Fs),
- OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Gs)
- };
- // Debug only..
- VOID
- PrintReg (
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- Print ((CHAR16 *)L"EAX: %x ", SystemContext.SystemContextIa32->Eax);
- Print ((CHAR16 *)L"ECX: %x ", SystemContext.SystemContextIa32->Ecx);
- Print ((CHAR16 *)L"EDX: %x ", SystemContext.SystemContextIa32->Edx);
- Print ((CHAR16 *)L"EBX: %x ", SystemContext.SystemContextIa32->Ebx);
- Print ((CHAR16 *)L"ESP: %x ", SystemContext.SystemContextIa32->Esp);
- Print ((CHAR16 *)L"EBP: %x ", SystemContext.SystemContextIa32->Ebp);
- Print ((CHAR16 *)L"ESI: %x ", SystemContext.SystemContextIa32->Esi);
- Print ((CHAR16 *)L"EDI: %x ", SystemContext.SystemContextIa32->Edi);
- Print ((CHAR16 *)L"EIP: %x\n", SystemContext.SystemContextIa32->Eip);
- Print ((CHAR16 *)L"EFlags: %x\n", SystemContext.SystemContextIa32->Eflags);
- }
- // Debug only..
- VOID
- PrintDRreg (
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- Print ((CHAR16 *)L"DR0: %x ", SystemContext.SystemContextIa32->Dr0);
- Print ((CHAR16 *)L"DR1: %x ", SystemContext.SystemContextIa32->Dr1);
- Print ((CHAR16 *)L"DR2: %x ", SystemContext.SystemContextIa32->Dr2);
- Print ((CHAR16 *)L"DR3: %x ", SystemContext.SystemContextIa32->Dr3);
- Print ((CHAR16 *)L"DR6: %x ", SystemContext.SystemContextIa32->Dr6);
- Print ((CHAR16 *)L"DR7: %x\n", SystemContext.SystemContextIa32->Dr7);
- }
- /**
- Return the number of entries in the gExceptionType[]
- @retval UINTN, the number of entries in the gExceptionType[] array.
- **/
- UINTN
- MaxEfiException (
- VOID
- )
- {
- return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
- }
- /**
- Return the number of entries in the gRegisters[]
- @retval UINTN, the number of entries (registers) in the gRegisters[] array.
- **/
- UINTN
- MaxRegisterCount (
- VOID
- )
- {
- return sizeof (gRegisterOffsets)/sizeof (UINTN);
- }
- /**
- Check to see if the ISA is supported.
- ISA = Instruction Set Architecture
- @retval TRUE if Isa is supported,
- FALSE otherwise.
- **/
- BOOLEAN
- CheckIsa (
- IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
- )
- {
- return (BOOLEAN)(Isa == IsaIa32);
- }
- /**
- This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
- It is, by default, set to find the register pointer of the IA32 member
- @param SystemContext Register content at time of the exception
- @param RegNumber The register to which we want to find a pointer
- @retval the pointer to the RegNumber-th pointer
- **/
- UINTN *
- FindPointerToRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN RegNumber
- )
- {
- UINT8 *TempPtr;
- TempPtr = ((UINT8 *)SystemContext.SystemContextIa32) + gRegisterOffsets[RegNumber];
- return (UINTN *)TempPtr;
- }
- /**
- Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
- @param SystemContext Register content at time of the exception
- @param RegNumber the number of the register that we want to read
- @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
- @retval the pointer to the next character of the output buffer that is available to be written on.
- **/
- CHAR8 *
- BasicReadRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN RegNumber,
- IN CHAR8 *OutBufPtr
- )
- {
- UINTN RegSize;
- RegSize = 0;
- while (RegSize < REG_SIZE) {
- *OutBufPtr++ = mHexToStr[((*FindPointerToRegister (SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
- *OutBufPtr++ = mHexToStr[((*FindPointerToRegister (SystemContext, RegNumber) >> RegSize) & 0xf)];
- RegSize = RegSize + 8;
- }
- return OutBufPtr;
- }
- /** ‘p n’
- Reads the n-th register's value into an output buffer and sends it as a packet
- @param SystemContext Register content at time of the exception
- @param InBuffer Pointer to the input buffer received from gdb server
- **/
- VOID
- EFIAPI
- ReadNthRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN CHAR8 *InBuffer
- )
- {
- UINTN RegNumber;
- CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
- CHAR8 *OutBufPtr; // pointer to the output buffer
- RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
- if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount ())) {
- SendError (GDB_EINVALIDREGNUM);
- return;
- }
- OutBufPtr = OutBuffer;
- OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);
- *OutBufPtr = '\0'; // the end of the buffer
- SendPacket (OutBuffer);
- }
- /** ‘g’
- Reads the general registers into an output buffer and sends it as a packet
- @param SystemContext Register content at time of the exception
- **/
- VOID
- EFIAPI
- ReadGeneralRegisters (
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- UINTN i;
- CHAR8 OutBuffer[129]; // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
- CHAR8 *OutBufPtr; // pointer to the output buffer
- OutBufPtr = OutBuffer;
- for (i = 0; i < MaxRegisterCount (); i++) {
- // there are only 16 registers to read
- OutBufPtr = BasicReadRegister (SystemContext, i, OutBufPtr);
- }
- *OutBufPtr = '\0'; // the end of the buffer
- SendPacket (OutBuffer);
- }
- /**
- Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
- @param SystemContext Register content at time of the exception
- @param RegNumber the number of the register that we want to write
- @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
- @retval the pointer to the next character of the input buffer that can be used
- **/
- CHAR8 *
- BasicWriteRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN RegNumber,
- IN CHAR8 *InBufPtr
- )
- {
- UINTN RegSize;
- UINTN TempValue; // the value transferred from a hex char
- UINT32 NewValue; // the new value of the RegNumber-th Register
- NewValue = 0;
- RegSize = 0;
- while (RegSize < REG_SIZE) {
- TempValue = HexCharToInt (*InBufPtr++);
- if (TempValue < 0) {
- SendError (GDB_EBADMEMDATA);
- return NULL;
- }
- NewValue += (TempValue << (RegSize+4));
- TempValue = HexCharToInt (*InBufPtr++);
- if (TempValue < 0) {
- SendError (GDB_EBADMEMDATA);
- return NULL;
- }
- NewValue += (TempValue << RegSize);
- RegSize = RegSize + 8;
- }
- *(FindPointerToRegister (SystemContext, RegNumber)) = NewValue;
- return InBufPtr;
- }
- /** ‘P n...=r...’
- Writes the new value of n-th register received into the input buffer to the n-th register
- @param SystemContext Register content at time of the exception
- @param InBuffer Pointer to the input buffer received from gdb server
- **/
- VOID
- EFIAPI
- WriteNthRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN CHAR8 *InBuffer
- )
- {
- UINTN RegNumber;
- CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
- CHAR8 *RegNumBufPtr;
- CHAR8 *InBufPtr; // pointer to the input buffer
- // find the register number to write
- InBufPtr = &InBuffer[1];
- RegNumBufPtr = RegNumBuffer;
- while (*InBufPtr != '=') {
- *RegNumBufPtr++ = *InBufPtr++;
- }
- *RegNumBufPtr = '\0';
- RegNumber = AsciiStrHexToUintn (RegNumBuffer);
- // check if this is a valid Register Number
- if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount ())) {
- SendError (GDB_EINVALIDREGNUM);
- return;
- }
- InBufPtr++; // skips the '=' character
- BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
- SendSuccess ();
- }
- /** ‘G XX...’
- Writes the new values received into the input buffer to the general registers
- @param SystemContext Register content at time of the exception
- @param InBuffer Pointer to the input buffer received from gdb server
- **/
- VOID
- EFIAPI
- WriteGeneralRegisters (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN CHAR8 *InBuffer
- )
- {
- UINTN i;
- CHAR8 *InBufPtr; /// pointer to the input buffer
- // check to see if the buffer is the right size which is
- // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 129
- if (AsciiStrLen (InBuffer) != 129) {
- // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
- // Bad message. Message is not the right length
- SendError (GDB_EBADBUFSIZE);
- return;
- }
- InBufPtr = &InBuffer[1];
- // Read the new values for the registers from the input buffer to an array, NewValueArray.
- // The values in the array are in the gdb ordering
- for (i = 0; i < MaxRegisterCount (); i++) {
- // there are only 16 registers to write
- InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);
- }
- SendSuccess ();
- }
- /**
- Insert Single Step in the SystemContext
- @param SystemContext Register content at time of the exception
- **/
- VOID
- AddSingleStep (
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- SystemContext.SystemContextIa32->Eflags |= TF_BIT; // Setting the TF bit.
- }
- /**
- Remove Single Step in the SystemContext
- @param SystemContext Register content at time of the exception
- **/
- VOID
- RemoveSingleStep (
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- SystemContext.SystemContextIa32->Eflags &= ~TF_BIT; // clearing the TF bit.
- }
- /** ‘c [addr ]’
- Continue. addr is Address to resume. If addr is omitted, resume at current
- Address.
- @param SystemContext Register content at time of the exception
- **/
- VOID
- EFIAPI
- ContinueAtAddress (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN CHAR8 *PacketData
- )
- {
- if (PacketData[1] != '\0') {
- SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]);
- }
- }
- /** ‘s [addr ]’
- Single step. addr is the Address at which to resume. If addr is omitted, resume
- at same Address.
- @param SystemContext Register content at time of the exception
- **/
- VOID
- EFIAPI
- SingleStep (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN CHAR8 *PacketData
- )
- {
- if (PacketData[1] != '\0') {
- SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]);
- }
- AddSingleStep (SystemContext);
- }
- /**
- Returns breakpoint data address from DR0-DR3 based on the input breakpoint number
- @param SystemContext Register content at time of the exception
- @param BreakpointNumber Breakpoint number
- @retval Address Data address from DR0-DR3 based on the breakpoint number.
- **/
- UINTN
- GetBreakpointDataAddress (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN BreakpointNumber
- )
- {
- UINTN Address;
- if (BreakpointNumber == 1) {
- Address = SystemContext.SystemContextIa32->Dr0;
- } else if (BreakpointNumber == 2) {
- Address = SystemContext.SystemContextIa32->Dr1;
- } else if (BreakpointNumber == 3) {
- Address = SystemContext.SystemContextIa32->Dr2;
- } else if (BreakpointNumber == 4) {
- Address = SystemContext.SystemContextIa32->Dr3;
- } else {
- Address = 0;
- }
- return Address;
- }
- /**
- Returns currently detected breakpoint value based on the register DR6 B0-B3 field.
- If no breakpoint is detected then it returns 0.
- @param SystemContext Register content at time of the exception
- @retval {1-4} Currently detected breakpoint value
- @retval 0 No breakpoint detected.
- **/
- UINTN
- GetBreakpointDetected (
- IN EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- IA32_DR6 Dr6;
- UINTN BreakpointNumber;
- Dr6.UintN = SystemContext.SystemContextIa32->Dr6;
- if (Dr6.Bits.B0 == 1) {
- BreakpointNumber = 1;
- } else if (Dr6.Bits.B1 == 1) {
- BreakpointNumber = 2;
- } else if (Dr6.Bits.B2 == 1) {
- BreakpointNumber = 3;
- } else if (Dr6.Bits.B3 == 1) {
- BreakpointNumber = 4;
- } else {
- BreakpointNumber = 0; // No breakpoint detected
- }
- return BreakpointNumber;
- }
- /**
- Returns Breakpoint type (InstructionExecution, DataWrite, DataRead or DataReadWrite)
- based on the Breakpoint number
- @param SystemContext Register content at time of the exception
- @param BreakpointNumber Breakpoint number
- @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn field
- For unknown value, it returns NotSupported.
- **/
- BREAK_TYPE
- GetBreakpointType (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN BreakpointNumber
- )
- {
- IA32_DR7 Dr7;
- BREAK_TYPE Type = NotSupported; // Default is NotSupported type
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
- if (BreakpointNumber == 1) {
- Type = (BREAK_TYPE)Dr7.Bits.RW0;
- } else if (BreakpointNumber == 2) {
- Type = (BREAK_TYPE)Dr7.Bits.RW1;
- } else if (BreakpointNumber == 3) {
- Type = (BREAK_TYPE)Dr7.Bits.RW2;
- } else if (BreakpointNumber == 4) {
- Type = (BREAK_TYPE)Dr7.Bits.RW3;
- }
- return Type;
- }
- /**
- Parses Length and returns the length which DR7 LENn field accepts.
- For example: If we receive 1-Byte length then we should return 0.
- Zero gets written to DR7 LENn field.
- @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
- @retval Length Appropriate converted values which DR7 LENn field accepts.
- **/
- UINTN
- ConvertLengthData (
- IN UINTN Length
- )
- {
- if (Length == 1) {
- // 1-Byte length
- return 0;
- } else if (Length == 2) {
- // 2-Byte length
- return 1;
- } else if (Length == 4) {
- // 4-Byte length
- return 3;
- } else {
- // Undefined or 8-byte length
- return 2;
- }
- }
- /**
- Finds the next free debug register. If all the registers are occupied then
- EFI_OUT_OF_RESOURCES is returned.
- @param SystemContext Register content at time of the exception
- @param Register Register value (0 - 3 for the first free debug register)
- @retval EFI_STATUS Appropriate status value.
- **/
- EFI_STATUS
- FindNextFreeDebugRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- OUT UINTN *Register
- )
- {
- IA32_DR7 Dr7;
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
- if (Dr7.Bits.G0 == 0) {
- *Register = 0;
- } else if (Dr7.Bits.G1 == 0) {
- *Register = 1;
- } else if (Dr7.Bits.G2 == 0) {
- *Register = 2;
- } else if (Dr7.Bits.G3 == 0) {
- *Register = 3;
- } else {
- return EFI_OUT_OF_RESOURCES;
- }
- return EFI_SUCCESS;
- }
- /**
- Enables the debug register. Writes Address value to appropriate DR0-3 register.
- Sets LENn, Gn, RWn bits in DR7 register.
- @param SystemContext Register content at time of the exception
- @param Register Register value (0 - 3)
- @param Address Breakpoint address value
- @param Type Breakpoint type (Instruction, Data write, Data read
- or write etc.)
- @retval EFI_STATUS Appropriate status value.
- **/
- EFI_STATUS
- EnableDebugRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN Register,
- IN UINTN Address,
- IN UINTN Length,
- IN UINTN Type
- )
- {
- IA32_DR7 Dr7;
- // Convert length data
- Length = ConvertLengthData (Length);
- // For Instruction execution, length should be 0
- // (Ref. Intel reference manual 18.2.4)
- if ((Type == 0) && (Length != 0)) {
- return EFI_INVALID_PARAMETER;
- }
- // Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
- // software breakpoint. We should send empty packet in both these cases.
- if ((Type == (BREAK_TYPE)DataRead) ||
- (Type == (BREAK_TYPE)SoftwareBreakpoint))
- {
- return EFI_UNSUPPORTED;
- }
- // Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
- if (Register == 0) {
- SystemContext.SystemContextIa32->Dr0 = Address;
- Dr7.Bits.G0 = 1;
- Dr7.Bits.RW0 = Type;
- Dr7.Bits.LEN0 = Length;
- } else if (Register == 1) {
- SystemContext.SystemContextIa32->Dr1 = Address;
- Dr7.Bits.G1 = 1;
- Dr7.Bits.RW1 = Type;
- Dr7.Bits.LEN1 = Length;
- } else if (Register == 2) {
- SystemContext.SystemContextIa32->Dr2 = Address;
- Dr7.Bits.G2 = 1;
- Dr7.Bits.RW2 = Type;
- Dr7.Bits.LEN2 = Length;
- } else if (Register == 3) {
- SystemContext.SystemContextIa32->Dr3 = Address;
- Dr7.Bits.G3 = 1;
- Dr7.Bits.RW3 = Type;
- Dr7.Bits.LEN3 = Length;
- } else {
- return EFI_INVALID_PARAMETER;
- }
- // Update Dr7 with appropriate Gn, RWn and LENn bits
- SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
- return EFI_SUCCESS;
- }
- /**
- Returns register number 0 - 3 for the matching debug register.
- This function compares incoming Address, Type, Length and
- if there is a match then it returns the appropriate register number.
- In case of mismatch, function returns EFI_NOT_FOUND message.
- @param SystemContext Register content at time of the exception
- @param Address Breakpoint address value
- @param Length Breakpoint length value
- @param Type Breakpoint type (Instruction, Data write,
- Data read or write etc.)
- @param Register Register value to be returned
- @retval EFI_STATUS Appropriate status value.
- **/
- EFI_STATUS
- FindMatchingDebugRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN Address,
- IN UINTN Length,
- IN UINTN Type,
- OUT UINTN *Register
- )
- {
- IA32_DR7 Dr7;
- // Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
- // software breakpoint. We should send empty packet in both these cases.
- if ((Type == (BREAK_TYPE)DataRead) ||
- (Type == (BREAK_TYPE)SoftwareBreakpoint))
- {
- return EFI_UNSUPPORTED;
- }
- // Convert length data
- Length = ConvertLengthData (Length);
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
- if ((Dr7.Bits.G0 == 1) &&
- (Dr7.Bits.LEN0 == Length) &&
- (Dr7.Bits.RW0 == Type) &&
- (Address == SystemContext.SystemContextIa32->Dr0))
- {
- *Register = 0;
- } else if ((Dr7.Bits.G1 == 1) &&
- (Dr7.Bits.LEN1 == Length) &&
- (Dr7.Bits.RW1 == Type) &&
- (Address == SystemContext.SystemContextIa32->Dr1))
- {
- *Register = 1;
- } else if ((Dr7.Bits.G2 == 1) &&
- (Dr7.Bits.LEN2 == Length) &&
- (Dr7.Bits.RW2 == Type) &&
- (Address == SystemContext.SystemContextIa32->Dr2))
- {
- *Register = 2;
- } else if ((Dr7.Bits.G3 == 1) &&
- (Dr7.Bits.LEN3 == Length) &&
- (Dr7.Bits.RW3 == Type) &&
- (Address == SystemContext.SystemContextIa32->Dr3))
- {
- *Register = 3;
- } else {
- Print ((CHAR16 *)L"No match found..\n");
- return EFI_NOT_FOUND;
- }
- return EFI_SUCCESS;
- }
- /**
- Disables the particular debug register.
- @param SystemContext Register content at time of the exception
- @param Register Register to be disabled
- @retval EFI_STATUS Appropriate status value.
- **/
- EFI_STATUS
- DisableDebugRegister (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN UINTN Register
- )
- {
- IA32_DR7 Dr7;
- UINTN Address = 0;
- // Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
- Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
- if (Register == 0) {
- SystemContext.SystemContextIa32->Dr0 = Address;
- Dr7.Bits.G0 = 0;
- Dr7.Bits.RW0 = 0;
- Dr7.Bits.LEN0 = 0;
- } else if (Register == 1) {
- SystemContext.SystemContextIa32->Dr1 = Address;
- Dr7.Bits.G1 = 0;
- Dr7.Bits.RW1 = 0;
- Dr7.Bits.LEN1 = 0;
- } else if (Register == 2) {
- SystemContext.SystemContextIa32->Dr2 = Address;
- Dr7.Bits.G2 = 0;
- Dr7.Bits.RW2 = 0;
- Dr7.Bits.LEN2 = 0;
- } else if (Register == 3) {
- SystemContext.SystemContextIa32->Dr3 = Address;
- Dr7.Bits.G3 = 0;
- Dr7.Bits.RW3 = 0;
- Dr7.Bits.LEN3 = 0;
- } else {
- return EFI_INVALID_PARAMETER;
- }
- // Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
- SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
- return EFI_SUCCESS;
- }
- /**
- ‘Z1, [addr], [length]’
- ‘Z2, [addr], [length]’
- ‘Z3, [addr], [length]’
- ‘Z4, [addr], [length]’
- Insert hardware breakpoint/watchpoint at address addr of size length
- @param SystemContext Register content at time of the exception
- @param *PacketData Pointer to the Payload data for the packet
- **/
- VOID
- EFIAPI
- InsertBreakPoint (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN CHAR8 *PacketData
- )
- {
- UINTN Type;
- UINTN Address;
- UINTN Length;
- UINTN Register;
- EFI_STATUS Status;
- BREAK_TYPE BreakType = NotSupported;
- UINTN ErrorCode;
- ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
- if (ErrorCode > 0) {
- SendError ((UINT8)ErrorCode);
- return;
- }
- switch (Type) {
- case 0: // Software breakpoint
- BreakType = SoftwareBreakpoint;
- break;
- case 1: // Hardware breakpoint
- BreakType = InstructionExecution;
- break;
- case 2: // Write watchpoint
- BreakType = DataWrite;
- break;
- case 3: // Read watchpoint
- BreakType = DataRead;
- break;
- case 4: // Access watchpoint
- BreakType = DataReadWrite;
- break;
- default:
- Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type);
- SendError (GDB_EINVALIDBRKPOINTTYPE);
- return;
- }
- // Find next free debug register
- Status = FindNextFreeDebugRegister (SystemContext, &Register);
- if (EFI_ERROR (Status)) {
- Print ((CHAR16 *)L"No space left on device\n");
- SendError (GDB_ENOSPACE);
- return;
- }
- // Write Address, length data at particular DR register
- Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_UNSUPPORTED) {
- Print ((CHAR16 *)L"Not supported\n");
- SendNotSupported ();
- return;
- }
- Print ((CHAR16 *)L"Invalid argument\n");
- SendError (GDB_EINVALIDARG);
- return;
- }
- SendSuccess ();
- }
- /**
- ‘z1, [addr], [length]’
- ‘z2, [addr], [length]’
- ‘z3, [addr], [length]’
- ‘z4, [addr], [length]’
- Remove hardware breakpoint/watchpoint at address addr of size length
- @param *PacketData Pointer to the Payload data for the packet
- **/
- VOID
- EFIAPI
- RemoveBreakPoint (
- IN EFI_SYSTEM_CONTEXT SystemContext,
- IN CHAR8 *PacketData
- )
- {
- UINTN Type;
- UINTN Address;
- UINTN Length;
- UINTN Register;
- BREAK_TYPE BreakType = NotSupported;
- EFI_STATUS Status;
- UINTN ErrorCode;
- // Parse breakpoint packet data
- ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
- if (ErrorCode > 0) {
- SendError ((UINT8)ErrorCode);
- return;
- }
- switch (Type) {
- case 0: // Software breakpoint
- BreakType = SoftwareBreakpoint;
- break;
- case 1: // Hardware breakpoint
- BreakType = InstructionExecution;
- break;
- case 2: // Write watchpoint
- BreakType = DataWrite;
- break;
- case 3: // Read watchpoint
- BreakType = DataRead;
- break;
- case 4: // Access watchpoint
- BreakType = DataReadWrite;
- break;
- default:
- SendError (GDB_EINVALIDBRKPOINTTYPE);
- return;
- }
- // Find matching debug register
- Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_UNSUPPORTED) {
- Print ((CHAR16 *)L"Not supported.\n");
- SendNotSupported ();
- return;
- }
- Print ((CHAR16 *)L"No matching register found.\n");
- SendError (GDB_ENOSPACE);
- return;
- }
- // Remove breakpoint
- Status = DisableDebugRegister (SystemContext, Register);
- if (EFI_ERROR (Status)) {
- Print ((CHAR16 *)L"Invalid argument.\n");
- SendError (GDB_EINVALIDARG);
- return;
- }
- SendSuccess ();
- }
- VOID
- InitializeProcessor (
- VOID
- )
- {
- }
- BOOLEAN
- ValidateAddress (
- IN VOID *Address
- )
- {
- return TRUE;
- }
- BOOLEAN
- ValidateException (
- IN EFI_EXCEPTION_TYPE ExceptionType,
- IN OUT EFI_SYSTEM_CONTEXT SystemContext
- )
- {
- return TRUE;
- }
|