1 /** @file
2   Basic serial IO abstaction for GDB
3 
4   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include <Uefi.h>
17 #include <Library/GdbSerialLib.h>
18 #include <Library/PcdLib.h>
19 #include <Library/IoLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 
23 #include <Protocol/DebugPort.h>
24 
25 
26 EFI_DEBUGPORT_PROTOCOL  *gDebugPort = NULL;
27 UINTN                   gTimeOut = 0;
28 
29 /**
30   The constructor function initializes the UART.
31 
32   @param  ImageHandle   The firmware allocated handle for the EFI image.
33   @param  SystemTable   A pointer to the EFI System Table.
34 
35   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
36 
37 **/
38 RETURN_STATUS
39 EFIAPI
GdbSerialLibDebugPortConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)40 GdbSerialLibDebugPortConstructor (
41   IN EFI_HANDLE        ImageHandle,
42   IN EFI_SYSTEM_TABLE  *SystemTable
43   )
44 {
45   EFI_STATUS    Status;
46 
47   Status = gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **)&gDebugPort);
48   if (!EFI_ERROR (Status)) {
49     gTimeOut = PcdGet32 (PcdGdbMaxPacketRetryCount);
50     gDebugPort->Reset (gDebugPort);
51   }
52 
53   return Status;
54 }
55 
56 
57 
58 /**
59   Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
60   data buts, and stop bits on a serial device. This call is optional as the serial
61   port will be set up with defaults base on PCD values.
62 
63   @param  BaudRate         The requested baud rate. A BaudRate value of 0 will use the the
64                            device's default interface speed.
65   @param  Parity           The type of parity to use on this serial device. A Parity value of
66                            DefaultParity will use the device's default parity value.
67   @param  DataBits         The number of data bits to use on the serial device. A DataBits
68                            vaule of 0 will use the device's default data bit setting.
69   @param  StopBits         The number of stop bits to use on this serial device. A StopBits
70                            value of DefaultStopBits will use the device's default number of
71                            stop bits.
72 
73   @retval EFI_SUCCESS      The device was configured.
74   @retval EFI_DEVICE_ERROR The serial device could not be coonfigured.
75 
76 **/
77 RETURN_STATUS
78 EFIAPI
GdbSerialInit(IN UINT64 BaudRate,IN UINT8 Parity,IN UINT8 DataBits,IN UINT8 StopBits)79 GdbSerialInit (
80   IN UINT64     BaudRate,
81   IN UINT8      Parity,
82   IN UINT8      DataBits,
83   IN UINT8      StopBits
84   )
85 {
86   EFI_STATUS  Status;
87 
88   Status = gDebugPort->Reset (gDebugPort);
89   return Status;
90 }
91 
92 
93 /**
94   Check to see if a character is available from GDB. Do not read the character as that is
95   done via GdbGetChar().
96 
97   @return TRUE  - Character availible
98   @return FALSE - Character not availible
99 
100 **/
101 BOOLEAN
102 EFIAPI
GdbIsCharAvailable(VOID)103 GdbIsCharAvailable (
104   VOID
105   )
106 {
107   EFI_STATUS  Status;
108 
109   Status = gDebugPort->Poll (gDebugPort);
110 
111   return (Status == EFI_SUCCESS ? TRUE : FALSE);
112 }
113 
114 
115 /**
116   Get a character from GDB. This function must be able to run in interrupt context.
117 
118   @return A character from GDB
119 
120 **/
121 CHAR8
122 EFIAPI
GdbGetChar(VOID)123 GdbGetChar (
124   VOID
125   )
126 {
127   EFI_STATUS  Status;
128   CHAR8       Char;
129   UINTN       BufferSize;
130 
131   do {
132     BufferSize = sizeof (Char);
133     Status = gDebugPort->Read (gDebugPort, gTimeOut, &BufferSize, &Char);
134   } while (EFI_ERROR (Status) || BufferSize != sizeof (Char));
135 
136   return Char;
137 }
138 
139 
140 /**
141   Send a character to GDB. This function must be able to run in interrupt context.
142 
143 
144   @param  Char    Send a character to GDB
145 
146 **/
147 
148 VOID
149 EFIAPI
GdbPutChar(IN CHAR8 Char)150 GdbPutChar (
151   IN  CHAR8   Char
152   )
153 {
154   EFI_STATUS  Status;
155   UINTN       BufferSize;
156 
157   do {
158     BufferSize = sizeof (Char);
159     Status = gDebugPort->Write (gDebugPort, gTimeOut, &BufferSize, &Char);
160   } while (EFI_ERROR (Status) || BufferSize != sizeof (Char));
161 
162   return;
163 }
164 
165 /**
166   Send an ASCII string to GDB. This function must be able to run in interrupt context.
167 
168 
169   @param  String    Send a string to GDB
170 
171 **/
172 
173 VOID
GdbPutString(IN CHAR8 * String)174 GdbPutString (
175   IN CHAR8  *String
176   )
177 {
178  // We could performance enhance this function by calling gDebugPort->Write ()
179   while (*String != '\0') {
180     GdbPutChar (*String);
181     String++;
182   }
183 }
184 
185 
186 
187 
188