2 Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system
3 running GDB. One console for error information and another console for user input/output.
5 Basic packet format is $packet-data#checksum. So every command has 4 bytes of overhead: $,
6 #, 0, 0. The 0 and 0 are the ascii characters for the checksum.
9 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
11 SPDX-License-Identifier: BSD-2-Clause-Patent
15 #include <GdbStubInternal.h>
18 // Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c
19 // here we need to wait for the periodic callback to do this.
21 BOOLEAN gCtrlCBreakFlag
= FALSE
;
24 // If the periodic callback is called while we are processing an F packet we need
25 // to let the callback know to not read from the serial stream as it could steal
26 // characters from the F response packet
28 BOOLEAN gProcessingFPacket
= FALSE
;
31 Process a control-C break message.
33 Currently a place holder, remove the ASSERT when it gets implemented.
35 @param ErrNo Error information from the F reply packet or other source
39 GdbCtrlCBreakMessage (
43 // See D.10.5 of gdb.pdf
44 // This should look like a break message. Should look like SIGINT
46 /* TODO: Make sure if we should do anything with ErrNo */
47 // Turn on the global Ctrl-C flag.
48 gCtrlCBreakFlag
= TRUE
;
52 Parse the F reply packet and extract the return value and an ErrNo if it exists.
54 @param Packet Packet to parse like an F reply packet
55 @param ErrNo Buffer to hold Count bytes that were read
57 @retval -1 Error, not a valid F reply packet
58 @retval other Return the return code from the F reply packet
62 GdbParseFReplyPacket (
69 if (Packet
[0] != 'F') {
70 // A valid response would be an F packet
74 RetCode
= AsciiStrHexToUintn (&Packet
[1]);
77 for ( ; *Packet
!= '\0' && *Packet
!= ','; Packet
++) {
80 if (*Packet
== '\0') {
85 *ErrNo
= AsciiStrHexToUintn (++Packet
);
88 for ( ; *Packet
!= '\0' && *Packet
!= ','; Packet
++) {
91 if (*Packet
== '\0') {
95 if (*(++Packet
) == 'C') {
96 GdbCtrlCBreakMessage (*ErrNo
);
103 Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates
104 the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.
106 @param FileDescriptor Device to talk to.
107 @param Buffer Buffer to hold Count bytes that were read
108 @param Count Number of bytes to transfer.
111 @retval {other} Number of bytes read.
116 IN INTN FileDescriptor
,
125 BOOLEAN ReceiveDone
= FALSE
;
128 // "Fread,XX,YYYYYYYY,XX
130 // XX - FileDescriptor in ASCII
131 // YYYYYYYY - Buffer address in ASCII
132 // XX - Count in ASCII
135 Size
= AsciiSPrint (Packet
, sizeof (Packet
), "Fread,%x,%x,%x", FileDescriptor
, Buffer
, Count
);
136 // Packet array is too small if you got this ASSERT
137 ASSERT (Size
< sizeof (Packet
));
139 gProcessingFPacket
= TRUE
;
141 Print ((CHAR16
*)L
"Packet sent..\n");
145 ReceivePacket (Packet
, sizeof (Packet
));
146 Print ((CHAR16
*)L
"Command received..%c\n", Packet
[0]);
148 // Process GDB commands
150 // Write memory command.
151 // M addr,length:XX...
153 WriteToMemory (Packet
);
156 // Fretcode, errno, Ctrl-C flag
157 // retcode - Count read
159 // Once target receives F reply packet that means the previous
160 // transactions are finished.
169 } while (ReceiveDone
== FALSE
);
171 RetCode
= GdbParseFReplyPacket (Packet
, &ErrNo
);
172 Print ((CHAR16
*)L
"RetCode: %x..ErrNo: %x..\n", RetCode
, ErrNo
);
175 // Send error to the host if there is any.
176 SendError ((UINT8
)ErrNo
);
179 gProcessingFPacket
= FALSE
;
185 Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates
186 nothing was written. On error -1 is returned.
188 @param FileDescriptor Device to talk to.
189 @param Buffer Buffer to hold Count bytes that are to be written
190 @param Count Number of bytes to transfer.
193 @retval {other} Number of bytes written.
198 IN INTN FileDescriptor
,
199 OUT CONST VOID
*Buffer
,
207 BOOLEAN ReceiveDone
= FALSE
;
210 // #Fwrite,XX,YYYYYYYY,XX$SS
212 // XX - FileDescriptor in ASCII
213 // YYYYYYYY - Buffer address in ASCII
214 // XX - Count in ASCII
217 Size
= AsciiSPrint (Packet
, sizeof (Packet
), "Fwrite,%x,%x,%x", FileDescriptor
, Buffer
, Count
);
218 // Packet array is too small if you got this ASSERT
219 ASSERT (Size
< sizeof (Packet
));
222 Print ((CHAR16
*)L
"Packet sent..\n");
226 ReceivePacket (Packet
, sizeof (Packet
));
227 Print ((CHAR16
*)L
"Command received..%c\n", Packet
[0]);
229 // Process GDB commands
231 // Read memory command.
234 ReadFromMemory (Packet
);
237 // Fretcode, errno, Ctrl-C flag
238 // retcode - Count read
240 // Once target receives F reply packet that means the previous
241 // transactions are finished.
250 } while (ReceiveDone
== FALSE
);
252 RetCode
= GdbParseFReplyPacket (Packet
, &ErrNo
);
253 Print ((CHAR16
*)L
"RetCode: %x..ErrNo: %x..\n", RetCode
, ErrNo
);
255 // Send error to the host if there is any.
257 SendError ((UINT8
)ErrNo
);
264 Reset the serial device.
266 @param This Protocol instance pointer.
268 @retval EFI_SUCCESS The device was reset.
269 @retval EFI_DEVICE_ERROR The serial device could not be reset.
275 IN EFI_SERIAL_IO_PROTOCOL
*This
282 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
283 data buts, and stop bits on a serial device.
285 @param This Protocol instance pointer.
286 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the
287 device's default interface speed.
288 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
289 serial interface. A ReceiveFifoDepth value of 0 will use
290 the device's default FIFO depth.
291 @param Timeout The requested time out for a single character in microseconds.
292 This timeout applies to both the transmit and receive side of the
293 interface. A Timeout value of 0 will use the device's default time
295 @param Parity The type of parity to use on this serial device. A Parity value of
296 DefaultParity will use the device's default parity value.
297 @param DataBits The number of data bits to use on the serial device. A DataBits
298 value of 0 will use the device's default data bit setting.
299 @param StopBits The number of stop bits to use on this serial device. A StopBits
300 value of DefaultStopBits will use the device's default number of
303 @retval EFI_SUCCESS The device was reset.
304 @retval EFI_DEVICE_ERROR The serial device could not be reset.
309 GdbSerialSetAttributes (
310 IN EFI_SERIAL_IO_PROTOCOL
*This
,
312 IN UINT32 ReceiveFifoDepth
,
314 IN EFI_PARITY_TYPE Parity
,
316 IN EFI_STOP_BITS_TYPE StopBits
319 return EFI_UNSUPPORTED
;
323 Set the control bits on a serial device
325 @param This Protocol instance pointer.
326 @param Control Set the bits of Control that are settable.
328 @retval EFI_SUCCESS The new control bits were set on the serial device.
329 @retval EFI_UNSUPPORTED The serial device does not support this operation.
330 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
335 GdbSerialSetControl (
336 IN EFI_SERIAL_IO_PROTOCOL
*This
,
340 return EFI_UNSUPPORTED
;
344 Retrieves the status of the control bits on a serial device
346 @param This Protocol instance pointer.
347 @param Control A pointer to return the current Control signals from the serial device.
349 @retval EFI_SUCCESS The control bits were read from the serial device.
350 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
355 GdbSerialGetControl (
356 IN EFI_SERIAL_IO_PROTOCOL
*This
,
360 return EFI_UNSUPPORTED
;
364 Writes data to a serial device.
366 @param This Protocol instance pointer.
367 @param BufferSize On input, the size of the Buffer. On output, the amount of
368 data actually written.
369 @param Buffer The buffer of data to write
371 @retval EFI_SUCCESS The data was written.
372 @retval EFI_DEVICE_ERROR The device reported an error.
373 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
379 IN EFI_SERIAL_IO_PROTOCOL
*This
,
380 IN OUT UINTN
*BufferSize
,
384 GDB_SERIAL_DEV
*SerialDev
;
387 SerialDev
= GDB_SERIAL_DEV_FROM_THIS (This
);
389 Return
= GdbWrite (SerialDev
->OutFileDescriptor
, Buffer
, *BufferSize
);
390 if (Return
== (UINTN
)-1) {
391 return EFI_DEVICE_ERROR
;
394 if (Return
!= *BufferSize
) {
395 *BufferSize
= Return
;
402 Writes data to a serial device.
404 @param This Protocol instance pointer.
405 @param BufferSize On input, the size of the Buffer. On output, the amount of
406 data returned in Buffer.
407 @param Buffer The buffer to return the data into.
409 @retval EFI_SUCCESS The data was read.
410 @retval EFI_DEVICE_ERROR The device reported an error.
411 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
417 IN EFI_SERIAL_IO_PROTOCOL
*This
,
418 IN OUT UINTN
*BufferSize
,
422 GDB_SERIAL_DEV
*SerialDev
;
425 SerialDev
= GDB_SERIAL_DEV_FROM_THIS (This
);
427 Return
= GdbRead (SerialDev
->InFileDescriptor
, Buffer
, *BufferSize
);
428 if (Return
== (UINTN
)-1) {
429 return EFI_DEVICE_ERROR
;
432 if (Return
!= *BufferSize
) {
433 *BufferSize
= Return
;
440 // Template used to initialize the GDB Serial IO protocols
442 GDB_SERIAL_DEV gdbSerialDevTemplate
= {
443 GDB_SERIAL_DEV_SIGNATURE
,
447 SERIAL_IO_INTERFACE_REVISION
,
449 GdbSerialSetAttributes
,
460 1, // RceiveFifoDepth
468 HARDWARE_DEVICE_PATH
,
471 (UINT8
)(sizeof (VENDOR_DEVICE_PATH
) + sizeof (UINT32
)),
472 (UINT8
)((sizeof (VENDOR_DEVICE_PATH
) + sizeof (UINT32
)) >> 8)
475 EFI_SERIAL_IO_PROTOCOL_GUID
479 END_DEVICE_PATH_TYPE
,
480 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
482 (UINT8
)(sizeof (EFI_DEVICE_PATH_PROTOCOL
)),
483 (UINT8
)(sizeof (EFI_DEVICE_PATH_PROTOCOL
) >> 8)
492 Make two serial consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.
494 These console show up on the remote system running GDB
498 GdbInitializeSerialConsole (
503 GDB_SERIAL_DEV
*StdOutSerialDev
;
504 GDB_SERIAL_DEV
*StdErrSerialDev
;
506 // Use the template to make a copy of the Serial Console private data structure.
507 StdOutSerialDev
= AllocateCopyPool (sizeof (GDB_SERIAL_DEV
), &gdbSerialDevTemplate
);
508 ASSERT (StdOutSerialDev
!= NULL
);
510 // Fixup pointer after the copy
511 StdOutSerialDev
->SerialIo
.Mode
= &StdOutSerialDev
->SerialMode
;
513 StdErrSerialDev
= AllocateCopyPool (sizeof (GDB_SERIAL_DEV
), &gdbSerialDevTemplate
);
514 ASSERT (StdErrSerialDev
!= NULL
);
516 // Fixup pointer and modify stuff that is different for StdError
517 StdErrSerialDev
->SerialIo
.Mode
= &StdErrSerialDev
->SerialMode
;
518 StdErrSerialDev
->DevicePath
.Index
= 1;
519 StdErrSerialDev
->OutFileDescriptor
= GDB_STDERR
;
521 // Make a new handle with Serial IO protocol and its device path on it.
522 Status
= gBS
->InstallMultipleProtocolInterfaces (
523 &StdOutSerialDev
->Handle
,
524 &gEfiSerialIoProtocolGuid
,
525 &StdOutSerialDev
->SerialIo
,
526 &gEfiDevicePathProtocolGuid
,
527 &StdOutSerialDev
->DevicePath
,
530 ASSERT_EFI_ERROR (Status
);
532 // Make a new handle with Serial IO protocol and its device path on it.
533 Status
= gBS
->InstallMultipleProtocolInterfaces (
534 &StdErrSerialDev
->Handle
,
535 &gEfiSerialIoProtocolGuid
,
536 &StdErrSerialDev
->SerialIo
,
537 &gEfiDevicePathProtocolGuid
,
538 &StdErrSerialDev
->DevicePath
,
541 ASSERT_EFI_ERROR (Status
);