GdbSerialLib.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /** @file
  2. Basic serial IO abstraction for GDB
  3. Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Uefi.h>
  7. #include <Library/GdbSerialLib.h>
  8. #include <Library/PcdLib.h>
  9. #include <Library/IoLib.h>
  10. #include <Library/DebugLib.h>
  11. // ---------------------------------------------
  12. // UART Register Offsets
  13. // ---------------------------------------------
  14. #define BAUD_LOW_OFFSET 0x00
  15. #define BAUD_HIGH_OFFSET 0x01
  16. #define IER_OFFSET 0x01
  17. #define LCR_SHADOW_OFFSET 0x01
  18. #define FCR_SHADOW_OFFSET 0x02
  19. #define IR_CONTROL_OFFSET 0x02
  20. #define FCR_OFFSET 0x02
  21. #define EIR_OFFSET 0x02
  22. #define BSR_OFFSET 0x03
  23. #define LCR_OFFSET 0x03
  24. #define MCR_OFFSET 0x04
  25. #define LSR_OFFSET 0x05
  26. #define MSR_OFFSET 0x06
  27. // ---------------------------------------------
  28. // UART Register Bit Defines
  29. // ---------------------------------------------
  30. #define LSR_TXRDY 0x20U
  31. #define LSR_RXDA 0x01U
  32. #define DLAB 0x01U
  33. #define ENABLE_FIFO 0x01U
  34. #define CLEAR_FIFOS 0x06U
  35. // IO Port Base for the UART
  36. UINTN gPort;
  37. /**
  38. The constructor function initializes the UART.
  39. @param ImageHandle The firmware allocated handle for the EFI image.
  40. @param SystemTable A pointer to the EFI System Table.
  41. @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
  42. **/
  43. RETURN_STATUS
  44. EFIAPI
  45. GdbSerialLibConstructor (
  46. IN EFI_HANDLE ImageHandle,
  47. IN EFI_SYSTEM_TABLE *SystemTable
  48. )
  49. {
  50. UINT64 BaudRate;
  51. UINT8 DataBits;
  52. UINT8 Parity;
  53. UINT8 StopBits;
  54. gPort = (UINTN)PcdGet32 (PcdGdbUartPort);
  55. BaudRate = PcdGet64 (PcdGdbBaudRate);
  56. Parity = PcdGet8 (PcdGdbParity);
  57. DataBits = PcdGet8 (PcdGdbDataBits);
  58. StopBits = PcdGet8 (PcdGdbStopBits);
  59. return GdbSerialInit (BaudRate, Parity, DataBits, StopBits);
  60. }
  61. /**
  62. Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
  63. data buts, and stop bits on a serial device. This call is optional as the serial
  64. port will be set up with defaults base on PCD values.
  65. @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
  66. device's default interface speed.
  67. @param Parity The type of parity to use on this serial device. A Parity value of
  68. DefaultParity will use the device's default parity value.
  69. @param DataBits The number of data bits to use on the serial device. A DataBits
  70. value of 0 will use the device's default data bit setting.
  71. @param StopBits The number of stop bits to use on this serial device. A StopBits
  72. value of DefaultStopBits will use the device's default number of
  73. stop bits.
  74. @retval EFI_SUCCESS The device was configured.
  75. @retval EFI_DEVICE_ERROR The serial device could not be configured.
  76. **/
  77. RETURN_STATUS
  78. EFIAPI
  79. GdbSerialInit (
  80. IN UINT64 BaudRate,
  81. IN UINT8 Parity,
  82. IN UINT8 DataBits,
  83. IN UINT8 StopBits
  84. )
  85. {
  86. UINTN Divisor;
  87. UINT8 OutputData;
  88. UINT8 Data;
  89. UINT8 BreakSet = 0;
  90. //
  91. // We assume the UART has been turned on to decode gPort address range
  92. //
  93. //
  94. // Map 5..8 to 0..3
  95. //
  96. Data = (UINT8)(DataBits - (UINT8)5);
  97. //
  98. // Calculate divisor for baud generator
  99. //
  100. Divisor = 115200/(UINTN)BaudRate;
  101. //
  102. // Set communications format
  103. //
  104. OutputData = (UINT8)((DLAB << 7) | ((BreakSet << 6) | ((Parity << 3) | ((StopBits << 2) | Data))));
  105. IoWrite8 (gPort + LCR_OFFSET, OutputData);
  106. //
  107. // Configure baud rate
  108. //
  109. IoWrite8 (gPort + BAUD_HIGH_OFFSET, (UINT8)(Divisor >> 8));
  110. IoWrite8 (gPort + BAUD_LOW_OFFSET, (UINT8)(Divisor & 0xff));
  111. //
  112. // Switch back to bank 0
  113. //
  114. OutputData = (UINT8)((~DLAB<<7)|((BreakSet<<6)|((Parity<<3)|((StopBits<<2)| Data))));
  115. IoWrite8 (gPort + LCR_OFFSET, OutputData);
  116. // Not sure this is the right place to enable the FIFOs....
  117. // We probably need the FIFO enabled to not drop input
  118. IoWrite8 (gPort + FCR_SHADOW_OFFSET, ENABLE_FIFO);
  119. // Configure the UART hardware here
  120. return RETURN_SUCCESS;
  121. }
  122. /**
  123. Check to see if a character is available from GDB. Do not read the character as that is
  124. done via GdbGetChar().
  125. @return TRUE - Character available
  126. @return FALSE - Character not available
  127. **/
  128. BOOLEAN
  129. EFIAPI
  130. GdbIsCharAvailable (
  131. VOID
  132. )
  133. {
  134. UINT8 Data;
  135. Data = IoRead8 (gPort + LSR_OFFSET);
  136. return ((Data & LSR_RXDA) == LSR_RXDA);
  137. }
  138. /**
  139. Get a character from GDB. This function must be able to run in interrupt context.
  140. @return A character from GDB
  141. **/
  142. CHAR8
  143. EFIAPI
  144. GdbGetChar (
  145. VOID
  146. )
  147. {
  148. UINT8 Data;
  149. CHAR8 Char;
  150. // Wait for the serial port to be ready
  151. do {
  152. Data = IoRead8 (gPort + LSR_OFFSET);
  153. } while ((Data & LSR_RXDA) == 0);
  154. Char = IoRead8 (gPort);
  155. // Make this an DEBUG_INFO after we get everything debugged.
  156. DEBUG ((DEBUG_ERROR, "<%c<", Char));
  157. return Char;
  158. }
  159. /**
  160. Send a character to GDB. This function must be able to run in interrupt context.
  161. @param Char Send a character to GDB
  162. **/
  163. VOID
  164. EFIAPI
  165. GdbPutChar (
  166. IN CHAR8 Char
  167. )
  168. {
  169. UINT8 Data;
  170. // Make this an DEBUG_INFO after we get everything debugged.
  171. DEBUG ((DEBUG_ERROR, ">%c>", Char));
  172. // Wait for the serial port to be ready
  173. do {
  174. Data = IoRead8 (gPort + LSR_OFFSET);
  175. } while ((Data & LSR_TXRDY) == 0);
  176. IoWrite8 (gPort, Char);
  177. }
  178. /**
  179. Send an ASCII string to GDB. This function must be able to run in interrupt context.
  180. @param String Send a string to GDB
  181. **/
  182. VOID
  183. GdbPutString (
  184. IN CHAR8 *String
  185. )
  186. {
  187. while (*String != '\0') {
  188. GdbPutChar (*String);
  189. String++;
  190. }
  191. }