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