• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 
23 //---------------------------------------------
24 // UART Register Offsets
25 //---------------------------------------------
26 #define BAUD_LOW_OFFSET         0x00
27 #define BAUD_HIGH_OFFSET        0x01
28 #define IER_OFFSET              0x01
29 #define LCR_SHADOW_OFFSET       0x01
30 #define FCR_SHADOW_OFFSET       0x02
31 #define IR_CONTROL_OFFSET       0x02
32 #define FCR_OFFSET              0x02
33 #define EIR_OFFSET              0x02
34 #define BSR_OFFSET              0x03
35 #define LCR_OFFSET              0x03
36 #define MCR_OFFSET              0x04
37 #define LSR_OFFSET              0x05
38 #define MSR_OFFSET              0x06
39 
40 //---------------------------------------------
41 // UART Register Bit Defines
42 //---------------------------------------------
43 #define LSR_TXRDY               0x20
44 #define LSR_RXDA                0x01
45 #define DLAB                    0x01
46 #define ENABLE_FIFO             0x01
47 #define CLEAR_FIFOS             0x06
48 
49 
50 
51 // IO Port Base for the UART
52 UINTN gPort;
53 
54 
55 /**
56   The constructor function initializes the UART.
57 
58   @param  ImageHandle   The firmware allocated handle for the EFI image.
59   @param  SystemTable   A pointer to the EFI System Table.
60 
61   @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.
62 
63 **/
64 RETURN_STATUS
65 EFIAPI
GdbSerialLibConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)66 GdbSerialLibConstructor (
67   IN EFI_HANDLE        ImageHandle,
68   IN EFI_SYSTEM_TABLE  *SystemTable
69   )
70 {
71   UINT64    BaudRate;
72   UINT8     DataBits;
73   UINT8     Parity;
74   UINT8     StopBits;
75 
76   gPort = (UINTN)PcdGet32 (PcdGdbUartPort);
77 
78   BaudRate = PcdGet64 (PcdGdbBaudRate);
79   Parity   = PcdGet8 (PcdGdbParity);
80   DataBits = PcdGet8 (PcdGdbDataBits);
81   StopBits = PcdGet8 (PcdGdbStopBits);
82 
83   return GdbSerialInit (BaudRate, Parity, DataBits, StopBits);
84 }
85 
86 
87 
88 /**
89   Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
90   data buts, and stop bits on a serial device. This call is optional as the serial
91   port will be set up with defaults base on PCD values.
92 
93   @param  BaudRate         The requested baud rate. A BaudRate value of 0 will use the the
94                            device's default interface speed.
95   @param  Parity           The type of parity to use on this serial device. A Parity value of
96                            DefaultParity will use the device's default parity value.
97   @param  DataBits         The number of data bits to use on the serial device. A DataBits
98                            vaule of 0 will use the device's default data bit setting.
99   @param  StopBits         The number of stop bits to use on this serial device. A StopBits
100                            value of DefaultStopBits will use the device's default number of
101                            stop bits.
102 
103   @retval EFI_SUCCESS      The device was configured.
104   @retval EFI_DEVICE_ERROR The serial device could not be coonfigured.
105 
106 **/
107 RETURN_STATUS
108 EFIAPI
GdbSerialInit(IN UINT64 BaudRate,IN UINT8 Parity,IN UINT8 DataBits,IN UINT8 StopBits)109 GdbSerialInit (
110   IN UINT64     BaudRate,
111   IN UINT8      Parity,
112   IN UINT8      DataBits,
113   IN UINT8      StopBits
114   )
115 {
116   UINTN           Divisor;
117   UINT8           OutputData;
118   UINT8           Data;
119   UINT8           BreakSet = 0;
120 
121   //
122   // We assume the UART has been turned on to decode gPort address range
123   //
124 
125   //
126   // Map 5..8 to 0..3
127   //
128   Data = (UINT8) (DataBits - (UINT8)5);
129 
130   //
131   // Calculate divisor for baud generator
132   //
133   Divisor = 115200/(UINTN)BaudRate;
134 
135   //
136   // Set communications format
137   //
138   OutputData = (UINT8)((DLAB << 7) | ((BreakSet << 6) | ((Parity << 3) | ((StopBits << 2) | Data))));
139   IoWrite8 (gPort + LCR_OFFSET, OutputData);
140 
141   //
142   // Configure baud rate
143   //
144   IoWrite8 (gPort + BAUD_HIGH_OFFSET, (UINT8)(Divisor >> 8));
145   IoWrite8 (gPort + BAUD_LOW_OFFSET, (UINT8)(Divisor & 0xff));
146 
147 
148   //
149   // Switch back to bank 0
150   //
151   OutputData = (UINT8)((~DLAB<<7)|((BreakSet<<6)|((Parity<<3)|((StopBits<<2)| Data))));
152   IoWrite8 (gPort + LCR_OFFSET, OutputData);
153 
154   // Not sure this is the right place to enable the FIFOs....
155   // We probably need the FIFO enabled to not drop input
156   IoWrite8 (gPort + FCR_SHADOW_OFFSET, ENABLE_FIFO);
157 
158 
159   // Configure the UART hardware here
160   return RETURN_SUCCESS;
161 }
162 
163 
164 /**
165   Check to see if a character is available from GDB. Do not read the character as that is
166   done via GdbGetChar().
167 
168   @return TRUE  - Character available
169   @return FALSE - Character not available
170 
171 **/
172 BOOLEAN
173 EFIAPI
GdbIsCharAvailable(VOID)174 GdbIsCharAvailable (
175   VOID
176   )
177 {
178   UINT8   Data;
179 
180   Data = IoRead8 (gPort + LSR_OFFSET);
181 
182   return ((Data & LSR_RXDA) == LSR_RXDA);
183 }
184 
185 
186 /**
187   Get a character from GDB. This function must be able to run in interrupt context.
188 
189   @return A character from GDB
190 
191 **/
192 CHAR8
193 EFIAPI
GdbGetChar(VOID)194 GdbGetChar (
195   VOID
196   )
197 {
198   UINT8   Data;
199   CHAR8   Char;
200 
201   // Wait for the serial port to be ready
202   do {
203     Data = IoRead8 (gPort + LSR_OFFSET);
204   } while ((Data & LSR_RXDA) == 0);
205 
206   Char = IoRead8 (gPort);
207 
208   // Make this an EFI_D_INFO after we get everything debugged.
209   DEBUG ((EFI_D_ERROR, "<%c<", Char));
210   return Char;
211 }
212 
213 
214 /**
215   Send a character to GDB. This function must be able to run in interrupt context.
216 
217 
218   @param  Char    Send a character to GDB
219 
220 **/
221 
222 VOID
223 EFIAPI
GdbPutChar(IN CHAR8 Char)224 GdbPutChar (
225   IN  CHAR8   Char
226   )
227 {
228   UINT8   Data;
229 
230   // Make this an EFI_D_INFO after we get everything debugged.
231   DEBUG ((EFI_D_ERROR, ">%c>", Char));
232 
233   // Wait for the serial port to be ready
234   do {
235     Data = IoRead8 (gPort + LSR_OFFSET);
236   } while ((Data & LSR_TXRDY) == 0);
237 
238   IoWrite8 (gPort, Char);
239 }
240 
241 /**
242   Send an ASCII string to GDB. This function must be able to run in interrupt context.
243 
244 
245   @param  String    Send a string to GDB
246 
247 **/
248 
249 VOID
GdbPutString(IN CHAR8 * String)250 GdbPutString (
251   IN CHAR8  *String
252   )
253 {
254   while (*String != '\0') {
255     GdbPutChar (*String);
256     String++;
257   }
258 }
259 
260 
261 
262 
263