SerialIo.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. /** @file
  2. Install Serial IO Protocol that layers on top of a Debug Communication Library instance.
  3. Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "DxeDebugAgentLib.h"
  7. //
  8. // Serial I/O Protocol Interface definitions.
  9. //
  10. /**
  11. Reset serial device.
  12. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  13. @retval EFI_SUCCESS Reset successfully.
  14. **/
  15. EFI_STATUS
  16. EFIAPI
  17. SerialReset (
  18. IN EFI_SERIAL_IO_PROTOCOL *This
  19. );
  20. /**
  21. Set new attributes to a serial device.
  22. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  23. @param[in] BaudRate The baudrate of the serial device.
  24. @param[in] ReceiveFifoDepth The depth of receive FIFO buffer.
  25. @param[in] Timeout The request timeout for a single char.
  26. @param[in] Parity The type of parity used in serial device.
  27. @param[in] DataBits Number of databits used in serial device.
  28. @param[in] StopBits Number of stopbits used in serial device.
  29. @retval EFI_SUCCESS The new attributes were set.
  30. @retval EFI_INVALID_PARAMETER One or more attributes have an unsupported value.
  31. @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return).
  32. **/
  33. EFI_STATUS
  34. EFIAPI
  35. SerialSetAttributes (
  36. IN EFI_SERIAL_IO_PROTOCOL *This,
  37. IN UINT64 BaudRate,
  38. IN UINT32 ReceiveFifoDepth,
  39. IN UINT32 Timeout,
  40. IN EFI_PARITY_TYPE Parity,
  41. IN UINT8 DataBits,
  42. IN EFI_STOP_BITS_TYPE StopBits
  43. );
  44. /**
  45. Set Control Bits.
  46. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  47. @param[in] Control Control bits that can be settable.
  48. @retval EFI_SUCCESS New Control bits were set successfully.
  49. @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported.
  50. **/
  51. EFI_STATUS
  52. EFIAPI
  53. SerialSetControl (
  54. IN EFI_SERIAL_IO_PROTOCOL *This,
  55. IN UINT32 Control
  56. );
  57. /**
  58. Get ControlBits.
  59. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  60. @param[out] Control Control signals of the serial device.
  61. @retval EFI_SUCCESS Get Control signals successfully.
  62. **/
  63. EFI_STATUS
  64. EFIAPI
  65. SerialGetControl (
  66. IN EFI_SERIAL_IO_PROTOCOL *This,
  67. OUT UINT32 *Control
  68. );
  69. /**
  70. Write the specified number of bytes to serial device.
  71. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  72. @param[in, out] BufferSize On input the size of Buffer, on output the amount of
  73. data actually written.
  74. @param[in] Buffer The buffer of data to write.
  75. @retval EFI_SUCCESS The data were written successfully.
  76. @retval EFI_DEVICE_ERROR The device reported an error.
  77. @retval EFI_TIMEOUT The write operation was stopped due to timeout.
  78. **/
  79. EFI_STATUS
  80. EFIAPI
  81. SerialWrite (
  82. IN EFI_SERIAL_IO_PROTOCOL *This,
  83. IN OUT UINTN *BufferSize,
  84. IN VOID *Buffer
  85. );
  86. /**
  87. Read the specified number of bytes from serial device.
  88. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  89. @param[in, out] BufferSize On input the size of Buffer, on output the amount of
  90. data returned in buffer.
  91. @param[out] Buffer The buffer to return the data into.
  92. @retval EFI_SUCCESS The data were read successfully.
  93. @retval EFI_DEVICE_ERROR The device reported an error.
  94. @retval EFI_TIMEOUT The read operation was stopped due to timeout.
  95. **/
  96. EFI_STATUS
  97. EFIAPI
  98. SerialRead (
  99. IN EFI_SERIAL_IO_PROTOCOL *This,
  100. IN OUT UINTN *BufferSize,
  101. OUT VOID *Buffer
  102. );
  103. //
  104. // Serial Driver Defaults
  105. //
  106. #define SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH 1
  107. #define SERIAL_PORT_DEFAULT_TIMEOUT 1000000
  108. #define SERIAL_PORT_DEFAULT_CONTROL_MASK 0
  109. #define SERIAL_PORT_LOOPBACK_BUFFER_FULL BIT8
  110. //
  111. // EFI_SERIAL_IO_MODE instance
  112. //
  113. EFI_SERIAL_IO_MODE mSerialIoMode = {
  114. SERIAL_PORT_DEFAULT_CONTROL_MASK,
  115. SERIAL_PORT_DEFAULT_TIMEOUT,
  116. 0, // default BaudRate
  117. SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,
  118. 0, // default DataBits
  119. 0, // default Parity
  120. 0 // default StopBits
  121. };
  122. //
  123. // EFI_SERIAL_IO_PROTOCOL instance
  124. //
  125. EFI_SERIAL_IO_PROTOCOL mSerialIo = {
  126. SERIAL_IO_INTERFACE_REVISION,
  127. SerialReset,
  128. SerialSetAttributes,
  129. SerialSetControl,
  130. SerialGetControl,
  131. SerialWrite,
  132. SerialRead,
  133. &mSerialIoMode
  134. };
  135. //
  136. // Serial IO Device Path definition
  137. //
  138. typedef struct {
  139. VENDOR_DEVICE_PATH VendorDevicePath;
  140. UART_DEVICE_PATH UartDevicePath;
  141. EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
  142. } SERIAL_IO_DEVICE_PATH;
  143. //
  144. // Serial IO Device Patch instance
  145. //
  146. SERIAL_IO_DEVICE_PATH mSerialIoDevicePath = {
  147. {
  148. {
  149. HARDWARE_DEVICE_PATH,
  150. HW_VENDOR_DP,
  151. {
  152. (UINT8)(sizeof (VENDOR_DEVICE_PATH)),
  153. (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8)
  154. }
  155. },
  156. EFI_DEBUG_AGENT_GUID,
  157. },
  158. {
  159. {
  160. MESSAGING_DEVICE_PATH,
  161. MSG_UART_DP,
  162. {
  163. (UINT8)(sizeof (UART_DEVICE_PATH)),
  164. (UINT8)((sizeof (UART_DEVICE_PATH)) >> 8)
  165. }
  166. },
  167. 0,
  168. 0, // default BaudRate
  169. 0, // default DataBits
  170. 0, // default Parity
  171. 0, // default StopBits
  172. },
  173. {
  174. END_DEVICE_PATH_TYPE,
  175. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  176. {
  177. END_DEVICE_PATH_LENGTH,
  178. 0
  179. }
  180. }
  181. };
  182. #define DEBUG_SERIAL_IO_FIFO_DEPTH 10
  183. //
  184. // Data buffer for Terminal input character and Debug Symbols.
  185. // The depth is DEBUG_SERIAL_IO_FIFO_DEPTH.
  186. // Fields:
  187. // First UINT8: The index of the first data in array Data[].
  188. // Last UINT8: The index, which you can put a new data into array Data[].
  189. // Surplus UINT8: Identify how many data you can put into array Data[].
  190. // Data[] UINT8: An array, which used to store data.
  191. //
  192. typedef struct {
  193. UINT8 First;
  194. UINT8 Last;
  195. UINT8 Surplus;
  196. UINT8 Data[DEBUG_SERIAL_IO_FIFO_DEPTH];
  197. } DEBUG_SERIAL_FIFO;
  198. //
  199. // Global Variables
  200. //
  201. EFI_HANDLE mSerialIoHandle = NULL;
  202. UINTN mLoopbackBuffer = 0;
  203. DEBUG_SERIAL_FIFO mSerialFifoForTerminal = {
  204. 0, 0, DEBUG_SERIAL_IO_FIFO_DEPTH, { 0 }
  205. };
  206. DEBUG_SERIAL_FIFO mSerialFifoForDebug = {
  207. 0, 0, DEBUG_SERIAL_IO_FIFO_DEPTH, { 0 }
  208. };
  209. /**
  210. Detect whether specific FIFO is empty or not.
  211. @param[in] Fifo A pointer to the Data Structure DEBUG_SERIAL_FIFO.
  212. @return whether specific FIFO is empty or not.
  213. **/
  214. BOOLEAN
  215. IsDebugTerminalFifoEmpty (
  216. IN DEBUG_SERIAL_FIFO *Fifo
  217. )
  218. {
  219. if (Fifo->Surplus == DEBUG_SERIAL_IO_FIFO_DEPTH) {
  220. return TRUE;
  221. }
  222. return FALSE;
  223. }
  224. /**
  225. Detect whether specific FIFO is full or not.
  226. @param[in] Fifo A pointer to the Data Structure DEBUG_SERIAL_FIFO.
  227. @return whether specific FIFO is full or not.
  228. **/
  229. BOOLEAN
  230. IsDebugTerminalFifoFull (
  231. IN DEBUG_SERIAL_FIFO *Fifo
  232. )
  233. {
  234. if (Fifo->Surplus == 0) {
  235. return TRUE;
  236. }
  237. return FALSE;
  238. }
  239. /**
  240. Add data to specific FIFO.
  241. @param[in] Fifo A pointer to the Data Structure DEBUG_SERIAL_FIFO.
  242. @param[in] Data The data added to FIFO.
  243. @retval EFI_SUCCESS Add data to specific FIFO successfully.
  244. @retval EFI_OUT_OF_RESOURCE Failed to add data because FIFO is already full.
  245. **/
  246. EFI_STATUS
  247. DebugTerminalFifoAdd (
  248. IN DEBUG_SERIAL_FIFO *Fifo,
  249. IN UINT8 Data
  250. )
  251. {
  252. //
  253. // if FIFO full can not add data
  254. //
  255. if (IsDebugTerminalFifoFull (Fifo)) {
  256. return EFI_OUT_OF_RESOURCES;
  257. }
  258. //
  259. // FIFO is not full can add data
  260. //
  261. Fifo->Data[Fifo->Last] = Data;
  262. Fifo->Surplus--;
  263. Fifo->Last++;
  264. if (Fifo->Last == DEBUG_SERIAL_IO_FIFO_DEPTH) {
  265. Fifo->Last = 0;
  266. }
  267. return EFI_SUCCESS;
  268. }
  269. /**
  270. Remove data from specific FIFO.
  271. @param[in] Fifo A pointer to the Data Structure DEBUG_SERIAL_FIFO.
  272. @param[out] Data The data removed from FIFO.
  273. @retval EFI_SUCCESS Remove data from specific FIFO successfully.
  274. @retval EFI_OUT_OF_RESOURCE Failed to remove data because FIFO is empty.
  275. **/
  276. EFI_STATUS
  277. DebugTerminalFifoRemove (
  278. IN DEBUG_SERIAL_FIFO *Fifo,
  279. OUT UINT8 *Data
  280. )
  281. {
  282. //
  283. // if FIFO is empty, no data can remove
  284. //
  285. if (IsDebugTerminalFifoEmpty (Fifo)) {
  286. return EFI_OUT_OF_RESOURCES;
  287. }
  288. //
  289. // FIFO is not empty, can remove data
  290. //
  291. *Data = Fifo->Data[Fifo->First];
  292. Fifo->Surplus++;
  293. Fifo->First++;
  294. if (Fifo->First == DEBUG_SERIAL_IO_FIFO_DEPTH) {
  295. Fifo->First = 0;
  296. }
  297. return EFI_SUCCESS;
  298. }
  299. /**
  300. Install EFI Serial IO protocol based on Debug Communication Library.
  301. **/
  302. VOID
  303. InstallSerialIo (
  304. VOID
  305. )
  306. {
  307. EFI_STATUS Status;
  308. Status = gBS->InstallMultipleProtocolInterfaces (
  309. &mSerialIoHandle,
  310. &gEfiDevicePathProtocolGuid,
  311. &mSerialIoDevicePath,
  312. &gEfiSerialIoProtocolGuid,
  313. &mSerialIo,
  314. NULL
  315. );
  316. if (EFI_ERROR (Status)) {
  317. DEBUG ((DEBUG_ERROR, "Debug Agent: Failed to install EFI Serial IO Protocol on Debug Port!\n"));
  318. }
  319. }
  320. /**
  321. Reset serial device.
  322. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  323. @retval EFI_SUCCESS Reset successfully.
  324. **/
  325. EFI_STATUS
  326. EFIAPI
  327. SerialReset (
  328. IN EFI_SERIAL_IO_PROTOCOL *This
  329. )
  330. {
  331. mSerialIoMode.ControlMask = SERIAL_PORT_DEFAULT_CONTROL_MASK;
  332. mLoopbackBuffer = 0;
  333. //
  334. // Not reset serial device hardware indeed.
  335. //
  336. return EFI_SUCCESS;
  337. }
  338. /**
  339. Set new attributes to a serial device.
  340. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  341. @param[in] BaudRate The baudrate of the serial device.
  342. @param[in] ReceiveFifoDepth The depth of receive FIFO buffer.
  343. @param[in] Timeout The request timeout for a single char.
  344. @param[in] Parity The type of parity used in serial device.
  345. @param[in] DataBits Number of databits used in serial device.
  346. @param[in] StopBits Number of stopbits used in serial device.
  347. @retval EFI_SUCCESS The new attributes were set.
  348. @retval EFI_INVALID_PARAMETER One or more attributes have an unsupported value.
  349. @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return).
  350. **/
  351. EFI_STATUS
  352. EFIAPI
  353. SerialSetAttributes (
  354. IN EFI_SERIAL_IO_PROTOCOL *This,
  355. IN UINT64 BaudRate,
  356. IN UINT32 ReceiveFifoDepth,
  357. IN UINT32 Timeout,
  358. IN EFI_PARITY_TYPE Parity,
  359. IN UINT8 DataBits,
  360. IN EFI_STOP_BITS_TYPE StopBits
  361. )
  362. {
  363. //
  364. // The Debug Communication Library CAN NOT change communications parameters (if it has)
  365. // actually. Because it also has no any idea on what parameters are based on, we cannot
  366. // check the input parameters (like BaudRate, Parity, DataBits and StopBits).
  367. //
  368. //
  369. // Update the Timeout value in the mode structure based on the request.
  370. // The Debug Communication Library can not support a timeout on writes, but the timeout on
  371. // reads can be provided by this module.
  372. //
  373. if (Timeout == 0) {
  374. mSerialIoMode.Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
  375. } else {
  376. mSerialIoMode.Timeout = Timeout;
  377. }
  378. //
  379. // Update the ReceiveFifoDepth value in the mode structure based on the request.
  380. // This module assumes that the Debug Communication Library uses a FIFO depth of
  381. // SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH. The Debug Communication Library may actually be
  382. // using a larger FIFO, but there is no way to tell.
  383. //
  384. if ((ReceiveFifoDepth == 0) || (ReceiveFifoDepth >= SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH)) {
  385. mSerialIoMode.ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;
  386. } else {
  387. return EFI_INVALID_PARAMETER;
  388. }
  389. return EFI_SUCCESS;
  390. }
  391. /**
  392. Set Control Bits.
  393. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  394. @param[in] Control Control bits that can be settable.
  395. @retval EFI_SUCCESS New Control bits were set successfully.
  396. @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported.
  397. **/
  398. EFI_STATUS
  399. EFIAPI
  400. SerialSetControl (
  401. IN EFI_SERIAL_IO_PROTOCOL *This,
  402. IN UINT32 Control
  403. )
  404. {
  405. //
  406. // The only control bit supported by this module is software loopback.
  407. // If any other bit is set, then return an error
  408. //
  409. if ((Control & (~EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE)) != 0) {
  410. return EFI_UNSUPPORTED;
  411. }
  412. mSerialIoMode.ControlMask = Control;
  413. return EFI_SUCCESS;
  414. }
  415. /**
  416. Get ControlBits.
  417. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  418. @param[out] Control Control signals of the serial device.
  419. @retval EFI_SUCCESS Get Control signals successfully.
  420. **/
  421. EFI_STATUS
  422. EFIAPI
  423. SerialGetControl (
  424. IN EFI_SERIAL_IO_PROTOCOL *This,
  425. OUT UINT32 *Control
  426. )
  427. {
  428. DEBUG_PORT_HANDLE Handle;
  429. BOOLEAN DebugTimerInterruptState;
  430. EFI_TPL Tpl;
  431. //
  432. // Raise TPL to prevent recursion from EFI timer interrupts
  433. //
  434. Tpl = gBS->RaiseTPL (TPL_NOTIFY);
  435. //
  436. // Save and disable Debug Timer interrupt to avoid it to access Debug Port
  437. //
  438. DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
  439. Handle = GetDebugPortHandle ();
  440. //
  441. // Always assume the output buffer is empty and the Debug Communication Library can process
  442. // more write requests.
  443. //
  444. *Control = mSerialIoMode.ControlMask | EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
  445. //
  446. // Check to see if the Terminal FIFO is empty and
  447. // check to see if the input buffer in the Debug Communication Library is empty
  448. //
  449. if (!IsDebugTerminalFifoEmpty (&mSerialFifoForTerminal) || DebugPortPollBuffer (Handle)) {
  450. *Control &= ~EFI_SERIAL_INPUT_BUFFER_EMPTY;
  451. }
  452. //
  453. // Restore Debug Timer interrupt
  454. //
  455. SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
  456. //
  457. // Restore to original TPL
  458. //
  459. gBS->RestoreTPL (Tpl);
  460. return EFI_SUCCESS;
  461. }
  462. /**
  463. Write the specified number of bytes to serial device.
  464. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  465. @param[in, out] BufferSize On input the size of Buffer, on output the amount of
  466. data actually written.
  467. @param[in] Buffer The buffer of data to write.
  468. @retval EFI_SUCCESS The data were written successfully.
  469. @retval EFI_DEVICE_ERROR The device reported an error.
  470. @retval EFI_TIMEOUT The write operation was stopped due to timeout.
  471. **/
  472. EFI_STATUS
  473. EFIAPI
  474. SerialWrite (
  475. IN EFI_SERIAL_IO_PROTOCOL *This,
  476. IN OUT UINTN *BufferSize,
  477. IN VOID *Buffer
  478. )
  479. {
  480. DEBUG_PORT_HANDLE Handle;
  481. BOOLEAN DebugTimerInterruptState;
  482. EFI_TPL Tpl;
  483. //
  484. // Raise TPL to prevent recursion from EFI timer interrupts
  485. //
  486. Tpl = gBS->RaiseTPL (TPL_NOTIFY);
  487. //
  488. // Save and disable Debug Timer interrupt to avoid it to access Debug Port
  489. //
  490. DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
  491. Handle = GetDebugPortHandle ();
  492. if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0) {
  493. if (*BufferSize == 0) {
  494. return EFI_SUCCESS;
  495. }
  496. if ((mLoopbackBuffer & SERIAL_PORT_LOOPBACK_BUFFER_FULL) != 0) {
  497. *BufferSize = 0;
  498. return EFI_TIMEOUT;
  499. }
  500. mLoopbackBuffer = SERIAL_PORT_LOOPBACK_BUFFER_FULL | *(UINT8 *)Buffer;
  501. *BufferSize = 1;
  502. } else {
  503. *BufferSize = DebugPortWriteBuffer (Handle, Buffer, *BufferSize);
  504. }
  505. //
  506. // Restore Debug Timer interrupt
  507. //
  508. SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
  509. //
  510. // Restore to original TPL
  511. //
  512. gBS->RestoreTPL (Tpl);
  513. return EFI_SUCCESS;
  514. }
  515. /**
  516. Read the specified number of bytes from serial device.
  517. @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL.
  518. @param[in, out] BufferSize On input the size of Buffer, on output the amount of
  519. data returned in buffer.
  520. @param[out] Buffer The buffer to return the data into.
  521. @retval EFI_SUCCESS The data were read successfully.
  522. @retval EFI_DEVICE_ERROR The device reported an error.
  523. @retval EFI_TIMEOUT The read operation was stopped due to timeout.
  524. **/
  525. EFI_STATUS
  526. EFIAPI
  527. SerialRead (
  528. IN EFI_SERIAL_IO_PROTOCOL *This,
  529. IN OUT UINTN *BufferSize,
  530. OUT VOID *Buffer
  531. )
  532. {
  533. EFI_STATUS Status;
  534. UINTN Index;
  535. UINT8 *Uint8Buffer;
  536. BOOLEAN DebugTimerInterruptState;
  537. EFI_TPL Tpl;
  538. DEBUG_PORT_HANDLE Handle;
  539. DEBUG_PACKET_HEADER DebugHeader;
  540. UINT8 *Data8;
  541. //
  542. // Raise TPL to prevent recursion from EFI timer interrupts
  543. //
  544. Tpl = gBS->RaiseTPL (TPL_NOTIFY);
  545. //
  546. // Save and disable Debug Timer interrupt to avoid it to access Debug Port
  547. //
  548. DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);
  549. Handle = GetDebugPortHandle ();
  550. Data8 = (UINT8 *)&DebugHeader;
  551. Uint8Buffer = (UINT8 *)Buffer;
  552. if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0) {
  553. if ((mLoopbackBuffer & SERIAL_PORT_LOOPBACK_BUFFER_FULL) == 0) {
  554. return EFI_TIMEOUT;
  555. }
  556. *Uint8Buffer = (UINT8)(mLoopbackBuffer & 0xff);
  557. mLoopbackBuffer = 0;
  558. *BufferSize = 1;
  559. } else {
  560. for (Index = 0; Index < *BufferSize; Index++) {
  561. //
  562. // Read input character from terminal FIFO firstly
  563. //
  564. Status = DebugTerminalFifoRemove (&mSerialFifoForTerminal, Data8);
  565. if (Status == EFI_SUCCESS) {
  566. *Uint8Buffer = *Data8;
  567. Uint8Buffer++;
  568. continue;
  569. }
  570. //
  571. // Read the input character from Debug Port
  572. //
  573. if (!DebugPortPollBuffer (Handle)) {
  574. break;
  575. }
  576. DebugAgentReadBuffer (Handle, Data8, 1, 0);
  577. if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
  578. //
  579. // Add the debug symbol into Debug FIFO
  580. //
  581. DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer attach symbol received %x", *Data8);
  582. DebugTerminalFifoAdd (&mSerialFifoForDebug, *Data8);
  583. } else if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {
  584. Status = ReadRemainingBreakPacket (Handle, &DebugHeader);
  585. if (Status == EFI_SUCCESS) {
  586. DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer break symbol received %x", DebugHeader.Command);
  587. DebugTerminalFifoAdd (&mSerialFifoForDebug, DebugHeader.Command);
  588. }
  589. if (Status == EFI_TIMEOUT) {
  590. continue;
  591. }
  592. } else {
  593. *Uint8Buffer = *Data8;
  594. Uint8Buffer++;
  595. }
  596. }
  597. *BufferSize = (UINTN)Uint8Buffer - (UINTN)Buffer;
  598. }
  599. //
  600. // Restore Debug Timer interrupt
  601. //
  602. SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);
  603. //
  604. // Restore to original TPL
  605. //
  606. gBS->RestoreTPL (Tpl);
  607. return EFI_SUCCESS;
  608. }
  609. /**
  610. Read the Attach/Break-in symbols from the debug port.
  611. @param[in] Handle Pointer to Debug Port handle.
  612. @param[out] BreakSymbol Returned break symbol.
  613. @retval EFI_SUCCESS Read the symbol in BreakSymbol.
  614. @retval EFI_NOT_FOUND No read the break symbol.
  615. **/
  616. EFI_STATUS
  617. DebugReadBreakFromDebugPort (
  618. IN DEBUG_PORT_HANDLE Handle,
  619. OUT UINT8 *BreakSymbol
  620. )
  621. {
  622. EFI_STATUS Status;
  623. DEBUG_PACKET_HEADER DebugHeader;
  624. UINT8 *Data8;
  625. *BreakSymbol = 0;
  626. //
  627. // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer empty.
  628. //
  629. Data8 = (UINT8 *)&DebugHeader;
  630. while (TRUE) {
  631. //
  632. // If start symbol is not received
  633. //
  634. if (!DebugPortPollBuffer (Handle)) {
  635. //
  636. // If no data in Debug Port, exit
  637. //
  638. break;
  639. }
  640. //
  641. // Try to read the start symbol
  642. //
  643. DebugAgentReadBuffer (Handle, Data8, 1, 0);
  644. if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {
  645. DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *Data8);
  646. *BreakSymbol = *Data8;
  647. return EFI_SUCCESS;
  648. }
  649. if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {
  650. Status = ReadRemainingBreakPacket (Handle, &DebugHeader);
  651. if (Status == EFI_SUCCESS) {
  652. DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer break symbol received %x", DebugHeader.Command);
  653. *BreakSymbol = DebugHeader.Command;
  654. return EFI_SUCCESS;
  655. }
  656. if (Status == EFI_TIMEOUT) {
  657. break;
  658. }
  659. } else {
  660. //
  661. // Add to Terminal FIFO
  662. //
  663. DebugTerminalFifoAdd (&mSerialFifoForTerminal, *Data8);
  664. }
  665. }
  666. return EFI_NOT_FOUND;
  667. }
  668. /**
  669. Read the Attach/Break-in symbols.
  670. @param[in] Handle Pointer to Debug Port handle.
  671. @param[out] BreakSymbol Returned break symbol.
  672. @retval EFI_SUCCESS Read the symbol in BreakSymbol.
  673. @retval EFI_NOT_FOUND No read the break symbol.
  674. **/
  675. EFI_STATUS
  676. DebugReadBreakSymbol (
  677. IN DEBUG_PORT_HANDLE Handle,
  678. OUT UINT8 *BreakSymbol
  679. )
  680. {
  681. EFI_STATUS Status;
  682. UINT8 Data8;
  683. //
  684. // Read break symbol from debug FIFO firstly
  685. //
  686. Status = DebugTerminalFifoRemove (&mSerialFifoForDebug, &Data8);
  687. if (Status == EFI_SUCCESS) {
  688. *BreakSymbol = Data8;
  689. return EFI_SUCCESS;
  690. } else {
  691. //
  692. // Read Break symbol from debug port
  693. //
  694. return DebugReadBreakFromDebugPort (Handle, BreakSymbol);
  695. }
  696. }