Processor.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972
  1. /** @file
  2. Processor specific parts of the GDB stub
  3. Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <GdbStubInternal.h>
  7. //
  8. // Array of exception types that need to be hooked by the debugger
  9. // {EFI mapping, GDB mapping}
  10. //
  11. EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
  12. { EXCEPT_IA32_DIVIDE_ERROR, GDB_SIGFPE },
  13. { EXCEPT_IA32_DEBUG, GDB_SIGTRAP },
  14. { EXCEPT_IA32_NMI, GDB_SIGEMT },
  15. { EXCEPT_IA32_BREAKPOINT, GDB_SIGTRAP },
  16. { EXCEPT_IA32_OVERFLOW, GDB_SIGSEGV },
  17. { EXCEPT_IA32_BOUND, GDB_SIGSEGV },
  18. { EXCEPT_IA32_INVALID_OPCODE, GDB_SIGILL },
  19. { EXCEPT_IA32_DOUBLE_FAULT, GDB_SIGEMT },
  20. { EXCEPT_IA32_STACK_FAULT, GDB_SIGSEGV },
  21. { EXCEPT_IA32_GP_FAULT, GDB_SIGSEGV },
  22. { EXCEPT_IA32_PAGE_FAULT, GDB_SIGSEGV },
  23. { EXCEPT_IA32_FP_ERROR, GDB_SIGEMT },
  24. { EXCEPT_IA32_ALIGNMENT_CHECK, GDB_SIGEMT },
  25. { EXCEPT_IA32_MACHINE_CHECK, GDB_SIGEMT }
  26. };
  27. // The offsets of registers SystemContext.
  28. // The fields in the array are in the gdb ordering.
  29. //
  30. // 16 regs
  31. UINTN gRegisterOffsets[] = {
  32. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Eax),
  33. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ecx),
  34. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Edx),
  35. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ebx),
  36. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Esp),
  37. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ebp),
  38. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Esi),
  39. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Edi),
  40. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Eip),
  41. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Eflags),
  42. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Cs),
  43. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ss),
  44. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Ds),
  45. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Es),
  46. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Fs),
  47. OFFSET_OF (EFI_SYSTEM_CONTEXT_IA32, Gs)
  48. };
  49. // Debug only..
  50. VOID
  51. PrintReg (
  52. IN EFI_SYSTEM_CONTEXT SystemContext
  53. )
  54. {
  55. Print ((CHAR16 *)L"EAX: %x ", SystemContext.SystemContextIa32->Eax);
  56. Print ((CHAR16 *)L"ECX: %x ", SystemContext.SystemContextIa32->Ecx);
  57. Print ((CHAR16 *)L"EDX: %x ", SystemContext.SystemContextIa32->Edx);
  58. Print ((CHAR16 *)L"EBX: %x ", SystemContext.SystemContextIa32->Ebx);
  59. Print ((CHAR16 *)L"ESP: %x ", SystemContext.SystemContextIa32->Esp);
  60. Print ((CHAR16 *)L"EBP: %x ", SystemContext.SystemContextIa32->Ebp);
  61. Print ((CHAR16 *)L"ESI: %x ", SystemContext.SystemContextIa32->Esi);
  62. Print ((CHAR16 *)L"EDI: %x ", SystemContext.SystemContextIa32->Edi);
  63. Print ((CHAR16 *)L"EIP: %x\n", SystemContext.SystemContextIa32->Eip);
  64. Print ((CHAR16 *)L"EFlags: %x\n", SystemContext.SystemContextIa32->Eflags);
  65. }
  66. // Debug only..
  67. VOID
  68. PrintDRreg (
  69. IN EFI_SYSTEM_CONTEXT SystemContext
  70. )
  71. {
  72. Print ((CHAR16 *)L"DR0: %x ", SystemContext.SystemContextIa32->Dr0);
  73. Print ((CHAR16 *)L"DR1: %x ", SystemContext.SystemContextIa32->Dr1);
  74. Print ((CHAR16 *)L"DR2: %x ", SystemContext.SystemContextIa32->Dr2);
  75. Print ((CHAR16 *)L"DR3: %x ", SystemContext.SystemContextIa32->Dr3);
  76. Print ((CHAR16 *)L"DR6: %x ", SystemContext.SystemContextIa32->Dr6);
  77. Print ((CHAR16 *)L"DR7: %x\n", SystemContext.SystemContextIa32->Dr7);
  78. }
  79. /**
  80. Return the number of entries in the gExceptionType[]
  81. @retval UINTN, the number of entries in the gExceptionType[] array.
  82. **/
  83. UINTN
  84. MaxEfiException (
  85. VOID
  86. )
  87. {
  88. return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
  89. }
  90. /**
  91. Return the number of entries in the gRegisters[]
  92. @retval UINTN, the number of entries (registers) in the gRegisters[] array.
  93. **/
  94. UINTN
  95. MaxRegisterCount (
  96. VOID
  97. )
  98. {
  99. return sizeof (gRegisterOffsets)/sizeof (UINTN);
  100. }
  101. /**
  102. Check to see if the ISA is supported.
  103. ISA = Instruction Set Architecture
  104. @retval TRUE if Isa is supported,
  105. FALSE otherwise.
  106. **/
  107. BOOLEAN
  108. CheckIsa (
  109. IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
  110. )
  111. {
  112. return (BOOLEAN)(Isa == IsaIa32);
  113. }
  114. /**
  115. This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
  116. It is, by default, set to find the register pointer of the IA32 member
  117. @param SystemContext Register content at time of the exception
  118. @param RegNumber The register to which we want to find a pointer
  119. @retval the pointer to the RegNumber-th pointer
  120. **/
  121. UINTN *
  122. FindPointerToRegister (
  123. IN EFI_SYSTEM_CONTEXT SystemContext,
  124. IN UINTN RegNumber
  125. )
  126. {
  127. UINT8 *TempPtr;
  128. TempPtr = ((UINT8 *)SystemContext.SystemContextIa32) + gRegisterOffsets[RegNumber];
  129. return (UINTN *)TempPtr;
  130. }
  131. /**
  132. Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
  133. @param SystemContext Register content at time of the exception
  134. @param RegNumber the number of the register that we want to read
  135. @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
  136. @retval the pointer to the next character of the output buffer that is available to be written on.
  137. **/
  138. CHAR8 *
  139. BasicReadRegister (
  140. IN EFI_SYSTEM_CONTEXT SystemContext,
  141. IN UINTN RegNumber,
  142. IN CHAR8 *OutBufPtr
  143. )
  144. {
  145. UINTN RegSize;
  146. RegSize = 0;
  147. while (RegSize < REG_SIZE) {
  148. *OutBufPtr++ = mHexToStr[((*FindPointerToRegister (SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
  149. *OutBufPtr++ = mHexToStr[((*FindPointerToRegister (SystemContext, RegNumber) >> RegSize) & 0xf)];
  150. RegSize = RegSize + 8;
  151. }
  152. return OutBufPtr;
  153. }
  154. /** ‘p n’
  155. Reads the n-th register's value into an output buffer and sends it as a packet
  156. @param SystemContext Register content at time of the exception
  157. @param InBuffer Pointer to the input buffer received from gdb server
  158. **/
  159. VOID
  160. EFIAPI
  161. ReadNthRegister (
  162. IN EFI_SYSTEM_CONTEXT SystemContext,
  163. IN CHAR8 *InBuffer
  164. )
  165. {
  166. UINTN RegNumber;
  167. CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
  168. CHAR8 *OutBufPtr; // pointer to the output buffer
  169. RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
  170. if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount ())) {
  171. SendError (GDB_EINVALIDREGNUM);
  172. return;
  173. }
  174. OutBufPtr = OutBuffer;
  175. OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);
  176. *OutBufPtr = '\0'; // the end of the buffer
  177. SendPacket (OutBuffer);
  178. }
  179. /** ‘g’
  180. Reads the general registers into an output buffer and sends it as a packet
  181. @param SystemContext Register content at time of the exception
  182. **/
  183. VOID
  184. EFIAPI
  185. ReadGeneralRegisters (
  186. IN EFI_SYSTEM_CONTEXT SystemContext
  187. )
  188. {
  189. UINTN i;
  190. CHAR8 OutBuffer[129]; // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
  191. CHAR8 *OutBufPtr; // pointer to the output buffer
  192. OutBufPtr = OutBuffer;
  193. for (i = 0; i < MaxRegisterCount (); i++) {
  194. // there are only 16 registers to read
  195. OutBufPtr = BasicReadRegister (SystemContext, i, OutBufPtr);
  196. }
  197. *OutBufPtr = '\0'; // the end of the buffer
  198. SendPacket (OutBuffer);
  199. }
  200. /**
  201. Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
  202. @param SystemContext Register content at time of the exception
  203. @param RegNumber the number of the register that we want to write
  204. @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
  205. @retval the pointer to the next character of the input buffer that can be used
  206. **/
  207. CHAR8 *
  208. BasicWriteRegister (
  209. IN EFI_SYSTEM_CONTEXT SystemContext,
  210. IN UINTN RegNumber,
  211. IN CHAR8 *InBufPtr
  212. )
  213. {
  214. UINTN RegSize;
  215. UINTN TempValue; // the value transferred from a hex char
  216. UINT32 NewValue; // the new value of the RegNumber-th Register
  217. NewValue = 0;
  218. RegSize = 0;
  219. while (RegSize < REG_SIZE) {
  220. TempValue = HexCharToInt (*InBufPtr++);
  221. if (TempValue < 0) {
  222. SendError (GDB_EBADMEMDATA);
  223. return NULL;
  224. }
  225. NewValue += (TempValue << (RegSize+4));
  226. TempValue = HexCharToInt (*InBufPtr++);
  227. if (TempValue < 0) {
  228. SendError (GDB_EBADMEMDATA);
  229. return NULL;
  230. }
  231. NewValue += (TempValue << RegSize);
  232. RegSize = RegSize + 8;
  233. }
  234. *(FindPointerToRegister (SystemContext, RegNumber)) = NewValue;
  235. return InBufPtr;
  236. }
  237. /** ‘P n...=r...’
  238. Writes the new value of n-th register received into the input buffer to the n-th register
  239. @param SystemContext Register content at time of the exception
  240. @param InBuffer Pointer to the input buffer received from gdb server
  241. **/
  242. VOID
  243. EFIAPI
  244. WriteNthRegister (
  245. IN EFI_SYSTEM_CONTEXT SystemContext,
  246. IN CHAR8 *InBuffer
  247. )
  248. {
  249. UINTN RegNumber;
  250. CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
  251. CHAR8 *RegNumBufPtr;
  252. CHAR8 *InBufPtr; // pointer to the input buffer
  253. // find the register number to write
  254. InBufPtr = &InBuffer[1];
  255. RegNumBufPtr = RegNumBuffer;
  256. while (*InBufPtr != '=') {
  257. *RegNumBufPtr++ = *InBufPtr++;
  258. }
  259. *RegNumBufPtr = '\0';
  260. RegNumber = AsciiStrHexToUintn (RegNumBuffer);
  261. // check if this is a valid Register Number
  262. if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount ())) {
  263. SendError (GDB_EINVALIDREGNUM);
  264. return;
  265. }
  266. InBufPtr++; // skips the '=' character
  267. BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
  268. SendSuccess ();
  269. }
  270. /** ‘G XX...’
  271. Writes the new values received into the input buffer to the general registers
  272. @param SystemContext Register content at time of the exception
  273. @param InBuffer Pointer to the input buffer received from gdb server
  274. **/
  275. VOID
  276. EFIAPI
  277. WriteGeneralRegisters (
  278. IN EFI_SYSTEM_CONTEXT SystemContext,
  279. IN CHAR8 *InBuffer
  280. )
  281. {
  282. UINTN i;
  283. CHAR8 *InBufPtr; /// pointer to the input buffer
  284. // check to see if the buffer is the right size which is
  285. // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 129
  286. if (AsciiStrLen (InBuffer) != 129) {
  287. // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
  288. // Bad message. Message is not the right length
  289. SendError (GDB_EBADBUFSIZE);
  290. return;
  291. }
  292. InBufPtr = &InBuffer[1];
  293. // Read the new values for the registers from the input buffer to an array, NewValueArray.
  294. // The values in the array are in the gdb ordering
  295. for (i = 0; i < MaxRegisterCount (); i++) {
  296. // there are only 16 registers to write
  297. InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);
  298. }
  299. SendSuccess ();
  300. }
  301. /**
  302. Insert Single Step in the SystemContext
  303. @param SystemContext Register content at time of the exception
  304. **/
  305. VOID
  306. AddSingleStep (
  307. IN EFI_SYSTEM_CONTEXT SystemContext
  308. )
  309. {
  310. SystemContext.SystemContextIa32->Eflags |= TF_BIT; // Setting the TF bit.
  311. }
  312. /**
  313. Remove Single Step in the SystemContext
  314. @param SystemContext Register content at time of the exception
  315. **/
  316. VOID
  317. RemoveSingleStep (
  318. IN EFI_SYSTEM_CONTEXT SystemContext
  319. )
  320. {
  321. SystemContext.SystemContextIa32->Eflags &= ~TF_BIT; // clearing the TF bit.
  322. }
  323. /** ‘c [addr ]’
  324. Continue. addr is Address to resume. If addr is omitted, resume at current
  325. Address.
  326. @param SystemContext Register content at time of the exception
  327. **/
  328. VOID
  329. EFIAPI
  330. ContinueAtAddress (
  331. IN EFI_SYSTEM_CONTEXT SystemContext,
  332. IN CHAR8 *PacketData
  333. )
  334. {
  335. if (PacketData[1] != '\0') {
  336. SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]);
  337. }
  338. }
  339. /** ‘s [addr ]’
  340. Single step. addr is the Address at which to resume. If addr is omitted, resume
  341. at same Address.
  342. @param SystemContext Register content at time of the exception
  343. **/
  344. VOID
  345. EFIAPI
  346. SingleStep (
  347. IN EFI_SYSTEM_CONTEXT SystemContext,
  348. IN CHAR8 *PacketData
  349. )
  350. {
  351. if (PacketData[1] != '\0') {
  352. SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]);
  353. }
  354. AddSingleStep (SystemContext);
  355. }
  356. /**
  357. Returns breakpoint data address from DR0-DR3 based on the input breakpoint number
  358. @param SystemContext Register content at time of the exception
  359. @param BreakpointNumber Breakpoint number
  360. @retval Address Data address from DR0-DR3 based on the breakpoint number.
  361. **/
  362. UINTN
  363. GetBreakpointDataAddress (
  364. IN EFI_SYSTEM_CONTEXT SystemContext,
  365. IN UINTN BreakpointNumber
  366. )
  367. {
  368. UINTN Address;
  369. if (BreakpointNumber == 1) {
  370. Address = SystemContext.SystemContextIa32->Dr0;
  371. } else if (BreakpointNumber == 2) {
  372. Address = SystemContext.SystemContextIa32->Dr1;
  373. } else if (BreakpointNumber == 3) {
  374. Address = SystemContext.SystemContextIa32->Dr2;
  375. } else if (BreakpointNumber == 4) {
  376. Address = SystemContext.SystemContextIa32->Dr3;
  377. } else {
  378. Address = 0;
  379. }
  380. return Address;
  381. }
  382. /**
  383. Returns currently detected breakpoint value based on the register DR6 B0-B3 field.
  384. If no breakpoint is detected then it returns 0.
  385. @param SystemContext Register content at time of the exception
  386. @retval {1-4} Currently detected breakpoint value
  387. @retval 0 No breakpoint detected.
  388. **/
  389. UINTN
  390. GetBreakpointDetected (
  391. IN EFI_SYSTEM_CONTEXT SystemContext
  392. )
  393. {
  394. IA32_DR6 Dr6;
  395. UINTN BreakpointNumber;
  396. Dr6.UintN = SystemContext.SystemContextIa32->Dr6;
  397. if (Dr6.Bits.B0 == 1) {
  398. BreakpointNumber = 1;
  399. } else if (Dr6.Bits.B1 == 1) {
  400. BreakpointNumber = 2;
  401. } else if (Dr6.Bits.B2 == 1) {
  402. BreakpointNumber = 3;
  403. } else if (Dr6.Bits.B3 == 1) {
  404. BreakpointNumber = 4;
  405. } else {
  406. BreakpointNumber = 0; // No breakpoint detected
  407. }
  408. return BreakpointNumber;
  409. }
  410. /**
  411. Returns Breakpoint type (InstructionExecution, DataWrite, DataRead or DataReadWrite)
  412. based on the Breakpoint number
  413. @param SystemContext Register content at time of the exception
  414. @param BreakpointNumber Breakpoint number
  415. @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn field
  416. For unknown value, it returns NotSupported.
  417. **/
  418. BREAK_TYPE
  419. GetBreakpointType (
  420. IN EFI_SYSTEM_CONTEXT SystemContext,
  421. IN UINTN BreakpointNumber
  422. )
  423. {
  424. IA32_DR7 Dr7;
  425. BREAK_TYPE Type = NotSupported; // Default is NotSupported type
  426. Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
  427. if (BreakpointNumber == 1) {
  428. Type = (BREAK_TYPE)Dr7.Bits.RW0;
  429. } else if (BreakpointNumber == 2) {
  430. Type = (BREAK_TYPE)Dr7.Bits.RW1;
  431. } else if (BreakpointNumber == 3) {
  432. Type = (BREAK_TYPE)Dr7.Bits.RW2;
  433. } else if (BreakpointNumber == 4) {
  434. Type = (BREAK_TYPE)Dr7.Bits.RW3;
  435. }
  436. return Type;
  437. }
  438. /**
  439. Parses Length and returns the length which DR7 LENn field accepts.
  440. For example: If we receive 1-Byte length then we should return 0.
  441. Zero gets written to DR7 LENn field.
  442. @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
  443. @retval Length Appropriate converted values which DR7 LENn field accepts.
  444. **/
  445. UINTN
  446. ConvertLengthData (
  447. IN UINTN Length
  448. )
  449. {
  450. if (Length == 1) {
  451. // 1-Byte length
  452. return 0;
  453. } else if (Length == 2) {
  454. // 2-Byte length
  455. return 1;
  456. } else if (Length == 4) {
  457. // 4-Byte length
  458. return 3;
  459. } else {
  460. // Undefined or 8-byte length
  461. return 2;
  462. }
  463. }
  464. /**
  465. Finds the next free debug register. If all the registers are occupied then
  466. EFI_OUT_OF_RESOURCES is returned.
  467. @param SystemContext Register content at time of the exception
  468. @param Register Register value (0 - 3 for the first free debug register)
  469. @retval EFI_STATUS Appropriate status value.
  470. **/
  471. EFI_STATUS
  472. FindNextFreeDebugRegister (
  473. IN EFI_SYSTEM_CONTEXT SystemContext,
  474. OUT UINTN *Register
  475. )
  476. {
  477. IA32_DR7 Dr7;
  478. Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
  479. if (Dr7.Bits.G0 == 0) {
  480. *Register = 0;
  481. } else if (Dr7.Bits.G1 == 0) {
  482. *Register = 1;
  483. } else if (Dr7.Bits.G2 == 0) {
  484. *Register = 2;
  485. } else if (Dr7.Bits.G3 == 0) {
  486. *Register = 3;
  487. } else {
  488. return EFI_OUT_OF_RESOURCES;
  489. }
  490. return EFI_SUCCESS;
  491. }
  492. /**
  493. Enables the debug register. Writes Address value to appropriate DR0-3 register.
  494. Sets LENn, Gn, RWn bits in DR7 register.
  495. @param SystemContext Register content at time of the exception
  496. @param Register Register value (0 - 3)
  497. @param Address Breakpoint address value
  498. @param Type Breakpoint type (Instruction, Data write, Data read
  499. or write etc.)
  500. @retval EFI_STATUS Appropriate status value.
  501. **/
  502. EFI_STATUS
  503. EnableDebugRegister (
  504. IN EFI_SYSTEM_CONTEXT SystemContext,
  505. IN UINTN Register,
  506. IN UINTN Address,
  507. IN UINTN Length,
  508. IN UINTN Type
  509. )
  510. {
  511. IA32_DR7 Dr7;
  512. // Convert length data
  513. Length = ConvertLengthData (Length);
  514. // For Instruction execution, length should be 0
  515. // (Ref. Intel reference manual 18.2.4)
  516. if ((Type == 0) && (Length != 0)) {
  517. return EFI_INVALID_PARAMETER;
  518. }
  519. // Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
  520. // software breakpoint. We should send empty packet in both these cases.
  521. if ((Type == (BREAK_TYPE)DataRead) ||
  522. (Type == (BREAK_TYPE)SoftwareBreakpoint))
  523. {
  524. return EFI_UNSUPPORTED;
  525. }
  526. // Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
  527. Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
  528. if (Register == 0) {
  529. SystemContext.SystemContextIa32->Dr0 = Address;
  530. Dr7.Bits.G0 = 1;
  531. Dr7.Bits.RW0 = Type;
  532. Dr7.Bits.LEN0 = Length;
  533. } else if (Register == 1) {
  534. SystemContext.SystemContextIa32->Dr1 = Address;
  535. Dr7.Bits.G1 = 1;
  536. Dr7.Bits.RW1 = Type;
  537. Dr7.Bits.LEN1 = Length;
  538. } else if (Register == 2) {
  539. SystemContext.SystemContextIa32->Dr2 = Address;
  540. Dr7.Bits.G2 = 1;
  541. Dr7.Bits.RW2 = Type;
  542. Dr7.Bits.LEN2 = Length;
  543. } else if (Register == 3) {
  544. SystemContext.SystemContextIa32->Dr3 = Address;
  545. Dr7.Bits.G3 = 1;
  546. Dr7.Bits.RW3 = Type;
  547. Dr7.Bits.LEN3 = Length;
  548. } else {
  549. return EFI_INVALID_PARAMETER;
  550. }
  551. // Update Dr7 with appropriate Gn, RWn and LENn bits
  552. SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
  553. return EFI_SUCCESS;
  554. }
  555. /**
  556. Returns register number 0 - 3 for the matching debug register.
  557. This function compares incoming Address, Type, Length and
  558. if there is a match then it returns the appropriate register number.
  559. In case of mismatch, function returns EFI_NOT_FOUND message.
  560. @param SystemContext Register content at time of the exception
  561. @param Address Breakpoint address value
  562. @param Length Breakpoint length value
  563. @param Type Breakpoint type (Instruction, Data write,
  564. Data read or write etc.)
  565. @param Register Register value to be returned
  566. @retval EFI_STATUS Appropriate status value.
  567. **/
  568. EFI_STATUS
  569. FindMatchingDebugRegister (
  570. IN EFI_SYSTEM_CONTEXT SystemContext,
  571. IN UINTN Address,
  572. IN UINTN Length,
  573. IN UINTN Type,
  574. OUT UINTN *Register
  575. )
  576. {
  577. IA32_DR7 Dr7;
  578. // Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
  579. // software breakpoint. We should send empty packet in both these cases.
  580. if ((Type == (BREAK_TYPE)DataRead) ||
  581. (Type == (BREAK_TYPE)SoftwareBreakpoint))
  582. {
  583. return EFI_UNSUPPORTED;
  584. }
  585. // Convert length data
  586. Length = ConvertLengthData (Length);
  587. Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
  588. if ((Dr7.Bits.G0 == 1) &&
  589. (Dr7.Bits.LEN0 == Length) &&
  590. (Dr7.Bits.RW0 == Type) &&
  591. (Address == SystemContext.SystemContextIa32->Dr0))
  592. {
  593. *Register = 0;
  594. } else if ((Dr7.Bits.G1 == 1) &&
  595. (Dr7.Bits.LEN1 == Length) &&
  596. (Dr7.Bits.RW1 == Type) &&
  597. (Address == SystemContext.SystemContextIa32->Dr1))
  598. {
  599. *Register = 1;
  600. } else if ((Dr7.Bits.G2 == 1) &&
  601. (Dr7.Bits.LEN2 == Length) &&
  602. (Dr7.Bits.RW2 == Type) &&
  603. (Address == SystemContext.SystemContextIa32->Dr2))
  604. {
  605. *Register = 2;
  606. } else if ((Dr7.Bits.G3 == 1) &&
  607. (Dr7.Bits.LEN3 == Length) &&
  608. (Dr7.Bits.RW3 == Type) &&
  609. (Address == SystemContext.SystemContextIa32->Dr3))
  610. {
  611. *Register = 3;
  612. } else {
  613. Print ((CHAR16 *)L"No match found..\n");
  614. return EFI_NOT_FOUND;
  615. }
  616. return EFI_SUCCESS;
  617. }
  618. /**
  619. Disables the particular debug register.
  620. @param SystemContext Register content at time of the exception
  621. @param Register Register to be disabled
  622. @retval EFI_STATUS Appropriate status value.
  623. **/
  624. EFI_STATUS
  625. DisableDebugRegister (
  626. IN EFI_SYSTEM_CONTEXT SystemContext,
  627. IN UINTN Register
  628. )
  629. {
  630. IA32_DR7 Dr7;
  631. UINTN Address = 0;
  632. // Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
  633. Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
  634. if (Register == 0) {
  635. SystemContext.SystemContextIa32->Dr0 = Address;
  636. Dr7.Bits.G0 = 0;
  637. Dr7.Bits.RW0 = 0;
  638. Dr7.Bits.LEN0 = 0;
  639. } else if (Register == 1) {
  640. SystemContext.SystemContextIa32->Dr1 = Address;
  641. Dr7.Bits.G1 = 0;
  642. Dr7.Bits.RW1 = 0;
  643. Dr7.Bits.LEN1 = 0;
  644. } else if (Register == 2) {
  645. SystemContext.SystemContextIa32->Dr2 = Address;
  646. Dr7.Bits.G2 = 0;
  647. Dr7.Bits.RW2 = 0;
  648. Dr7.Bits.LEN2 = 0;
  649. } else if (Register == 3) {
  650. SystemContext.SystemContextIa32->Dr3 = Address;
  651. Dr7.Bits.G3 = 0;
  652. Dr7.Bits.RW3 = 0;
  653. Dr7.Bits.LEN3 = 0;
  654. } else {
  655. return EFI_INVALID_PARAMETER;
  656. }
  657. // Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
  658. SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
  659. return EFI_SUCCESS;
  660. }
  661. /**
  662. ‘Z1, [addr], [length]’
  663. ‘Z2, [addr], [length]’
  664. ‘Z3, [addr], [length]’
  665. ‘Z4, [addr], [length]’
  666. Insert hardware breakpoint/watchpoint at address addr of size length
  667. @param SystemContext Register content at time of the exception
  668. @param *PacketData Pointer to the Payload data for the packet
  669. **/
  670. VOID
  671. EFIAPI
  672. InsertBreakPoint (
  673. IN EFI_SYSTEM_CONTEXT SystemContext,
  674. IN CHAR8 *PacketData
  675. )
  676. {
  677. UINTN Type;
  678. UINTN Address;
  679. UINTN Length;
  680. UINTN Register;
  681. EFI_STATUS Status;
  682. BREAK_TYPE BreakType = NotSupported;
  683. UINTN ErrorCode;
  684. ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
  685. if (ErrorCode > 0) {
  686. SendError ((UINT8)ErrorCode);
  687. return;
  688. }
  689. switch (Type) {
  690. case 0: // Software breakpoint
  691. BreakType = SoftwareBreakpoint;
  692. break;
  693. case 1: // Hardware breakpoint
  694. BreakType = InstructionExecution;
  695. break;
  696. case 2: // Write watchpoint
  697. BreakType = DataWrite;
  698. break;
  699. case 3: // Read watchpoint
  700. BreakType = DataRead;
  701. break;
  702. case 4: // Access watchpoint
  703. BreakType = DataReadWrite;
  704. break;
  705. default:
  706. Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type);
  707. SendError (GDB_EINVALIDBRKPOINTTYPE);
  708. return;
  709. }
  710. // Find next free debug register
  711. Status = FindNextFreeDebugRegister (SystemContext, &Register);
  712. if (EFI_ERROR (Status)) {
  713. Print ((CHAR16 *)L"No space left on device\n");
  714. SendError (GDB_ENOSPACE);
  715. return;
  716. }
  717. // Write Address, length data at particular DR register
  718. Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType);
  719. if (EFI_ERROR (Status)) {
  720. if (Status == EFI_UNSUPPORTED) {
  721. Print ((CHAR16 *)L"Not supported\n");
  722. SendNotSupported ();
  723. return;
  724. }
  725. Print ((CHAR16 *)L"Invalid argument\n");
  726. SendError (GDB_EINVALIDARG);
  727. return;
  728. }
  729. SendSuccess ();
  730. }
  731. /**
  732. ‘z1, [addr], [length]’
  733. ‘z2, [addr], [length]’
  734. ‘z3, [addr], [length]’
  735. ‘z4, [addr], [length]’
  736. Remove hardware breakpoint/watchpoint at address addr of size length
  737. @param *PacketData Pointer to the Payload data for the packet
  738. **/
  739. VOID
  740. EFIAPI
  741. RemoveBreakPoint (
  742. IN EFI_SYSTEM_CONTEXT SystemContext,
  743. IN CHAR8 *PacketData
  744. )
  745. {
  746. UINTN Type;
  747. UINTN Address;
  748. UINTN Length;
  749. UINTN Register;
  750. BREAK_TYPE BreakType = NotSupported;
  751. EFI_STATUS Status;
  752. UINTN ErrorCode;
  753. // Parse breakpoint packet data
  754. ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
  755. if (ErrorCode > 0) {
  756. SendError ((UINT8)ErrorCode);
  757. return;
  758. }
  759. switch (Type) {
  760. case 0: // Software breakpoint
  761. BreakType = SoftwareBreakpoint;
  762. break;
  763. case 1: // Hardware breakpoint
  764. BreakType = InstructionExecution;
  765. break;
  766. case 2: // Write watchpoint
  767. BreakType = DataWrite;
  768. break;
  769. case 3: // Read watchpoint
  770. BreakType = DataRead;
  771. break;
  772. case 4: // Access watchpoint
  773. BreakType = DataReadWrite;
  774. break;
  775. default:
  776. SendError (GDB_EINVALIDBRKPOINTTYPE);
  777. return;
  778. }
  779. // Find matching debug register
  780. Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register);
  781. if (EFI_ERROR (Status)) {
  782. if (Status == EFI_UNSUPPORTED) {
  783. Print ((CHAR16 *)L"Not supported.\n");
  784. SendNotSupported ();
  785. return;
  786. }
  787. Print ((CHAR16 *)L"No matching register found.\n");
  788. SendError (GDB_ENOSPACE);
  789. return;
  790. }
  791. // Remove breakpoint
  792. Status = DisableDebugRegister (SystemContext, Register);
  793. if (EFI_ERROR (Status)) {
  794. Print ((CHAR16 *)L"Invalid argument.\n");
  795. SendError (GDB_EINVALIDARG);
  796. return;
  797. }
  798. SendSuccess ();
  799. }
  800. VOID
  801. InitializeProcessor (
  802. VOID
  803. )
  804. {
  805. }
  806. BOOLEAN
  807. ValidateAddress (
  808. IN VOID *Address
  809. )
  810. {
  811. return TRUE;
  812. }
  813. BOOLEAN
  814. ValidateException (
  815. IN EFI_EXCEPTION_TYPE ExceptionType,
  816. IN OUT EFI_SYSTEM_CONTEXT SystemContext
  817. )
  818. {
  819. return TRUE;
  820. }