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