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