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
40 GdbCtrlCBreakMessage (
44 // See D.10.5 of gdb.pdf
45 // This should look like a break message. Should look like SIGINT
47 /* TODO: Make sure if we should do anything with ErrNo */
48 //Turn on the global Ctrl-C flag.
49 gCtrlCBreakFlag
= TRUE
;
54 Parse the F reply packet and extract the return value and an ErrNo if it exists.
56 @param Packet Packet to parse like an F reply packet
57 @param ErrNo Buffer to hold Count bytes that were read
59 @retval -1 Error, not a valid F reply packet
60 @retval other Return the return code from the F reply packet
64 GdbParseFReplyPacket (
71 if (Packet
[0] != 'F') {
72 // A valid response would be an F packet
76 RetCode
= AsciiStrHexToUintn (&Packet
[1]);
79 for (;*Packet
!= '\0' && *Packet
!= ','; Packet
++);
80 if (*Packet
== '\0') {
85 *ErrNo
= AsciiStrHexToUintn (++Packet
);
88 for (;*Packet
!= '\0' && *Packet
!= ','; Packet
++);
89 if (*Packet
== '\0') {
93 if (*(++Packet
) == 'C') {
94 GdbCtrlCBreakMessage (*ErrNo
);
102 Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates
103 the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.
105 @param FileDescriptor Device to talk to.
106 @param Buffer Buffer to hold Count bytes that were read
107 @param Count Number of bytes to transfer.
110 @retval {other} Number of bytes read.
115 IN INTN FileDescriptor
,
124 BOOLEAN ReceiveDone
= FALSE
;
127 // "Fread,XX,YYYYYYYY,XX
129 // XX - FileDescriptor in ASCII
130 // YYYYYYYY - Buffer address in ASCII
131 // XX - Count in ASCII
134 Size
= AsciiSPrint (Packet
, sizeof (Packet
), "Fread,%x,%x,%x", FileDescriptor
, Buffer
, Count
);
135 // Packet array is too small if you got this ASSERT
136 ASSERT (Size
< sizeof (Packet
));
138 gProcessingFPacket
= TRUE
;
140 Print ((CHAR16
*)L
"Packet sent..\n");
144 ReceivePacket (Packet
, sizeof (Packet
));
145 Print ((CHAR16
*)L
"Command received..%c\n", Packet
[0]);
147 // Process GDB commands
149 //Write memory command.
150 //M addr,length:XX...
152 WriteToMemory (Packet
);
155 //Fretcode, errno, Ctrl-C flag
156 //retcode - Count read
158 //Once target receives F reply packet that means the previous
159 //transactions are finished.
168 } while (ReceiveDone
== FALSE
);
170 RetCode
= GdbParseFReplyPacket (Packet
, &ErrNo
);
171 Print ((CHAR16
*)L
"RetCode: %x..ErrNo: %x..\n", RetCode
, ErrNo
);
174 //Send error to the host if there is any.
175 SendError ((UINT8
)ErrNo
);
178 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
);
265 Reset the serial device.
267 @param This Protocol instance pointer.
269 @retval EFI_SUCCESS The device was reset.
270 @retval EFI_DEVICE_ERROR The serial device could not be reset.
276 IN EFI_SERIAL_IO_PROTOCOL
*This
284 Sets the baud rate, receive FIFO depth, transmit/receive time out, parity,
285 data buts, and stop bits on a serial device.
287 @param This Protocol instance pointer.
288 @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
289 device's default interface speed.
290 @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the
291 serial interface. A ReceiveFifoDepth value of 0 will use
292 the device's default FIFO depth.
293 @param Timeout The requested time out for a single character in microseconds.
294 This timeout applies to both the transmit and receive side of the
295 interface. A Timeout value of 0 will use the device's default time
297 @param Parity The type of parity to use on this serial device. A Parity value of
298 DefaultParity will use the device's default parity value.
299 @param DataBits The number of data bits to use on the serial device. A DataBits
300 value of 0 will use the device's default data bit setting.
301 @param StopBits The number of stop bits to use on this serial device. A StopBits
302 value of DefaultStopBits will use the device's default number of
305 @retval EFI_SUCCESS The device was reset.
306 @retval EFI_DEVICE_ERROR The serial device could not be reset.
311 GdbSerialSetAttributes (
312 IN EFI_SERIAL_IO_PROTOCOL
*This
,
314 IN UINT32 ReceiveFifoDepth
,
316 IN EFI_PARITY_TYPE Parity
,
318 IN EFI_STOP_BITS_TYPE StopBits
321 return EFI_UNSUPPORTED
;
326 Set the control bits on a serial device
328 @param This Protocol instance pointer.
329 @param Control Set the bits of Control that are settable.
331 @retval EFI_SUCCESS The new control bits were set on the serial device.
332 @retval EFI_UNSUPPORTED The serial device does not support this operation.
333 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
338 GdbSerialSetControl (
339 IN EFI_SERIAL_IO_PROTOCOL
*This
,
343 return EFI_UNSUPPORTED
;
348 Retrieves the status of the control bits on a serial device
350 @param This Protocol instance pointer.
351 @param Control A pointer to return the current Control signals from the serial device.
353 @retval EFI_SUCCESS The control bits were read from the serial device.
354 @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
359 GdbSerialGetControl (
360 IN EFI_SERIAL_IO_PROTOCOL
*This
,
364 return EFI_UNSUPPORTED
;
369 Writes data to a serial device.
371 @param This Protocol instance pointer.
372 @param BufferSize On input, the size of the Buffer. On output, the amount of
373 data actually written.
374 @param Buffer The buffer of data to write
376 @retval EFI_SUCCESS The data was written.
377 @retval EFI_DEVICE_ERROR The device reported an error.
378 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
384 IN EFI_SERIAL_IO_PROTOCOL
*This
,
385 IN OUT UINTN
*BufferSize
,
389 GDB_SERIAL_DEV
*SerialDev
;
392 SerialDev
= GDB_SERIAL_DEV_FROM_THIS (This
);
394 Return
= GdbWrite (SerialDev
->OutFileDescriptor
, Buffer
, *BufferSize
);
395 if (Return
== (UINTN
)-1) {
396 return EFI_DEVICE_ERROR
;
399 if (Return
!= *BufferSize
) {
400 *BufferSize
= Return
;
407 Writes data to a serial device.
409 @param This Protocol instance pointer.
410 @param BufferSize On input, the size of the Buffer. On output, the amount of
411 data returned in Buffer.
412 @param Buffer The buffer to return the data into.
414 @retval EFI_SUCCESS The data was read.
415 @retval EFI_DEVICE_ERROR The device reported an error.
416 @retval EFI_TIMEOUT The data write was stopped due to a timeout.
423 IN EFI_SERIAL_IO_PROTOCOL
*This
,
424 IN OUT UINTN
*BufferSize
,
428 GDB_SERIAL_DEV
*SerialDev
;
431 SerialDev
= GDB_SERIAL_DEV_FROM_THIS (This
);
433 Return
= GdbRead (SerialDev
->InFileDescriptor
, Buffer
, *BufferSize
);
434 if (Return
== (UINTN
)-1) {
435 return EFI_DEVICE_ERROR
;
438 if (Return
!= *BufferSize
) {
439 *BufferSize
= Return
;
447 // Template used to initialize the GDB Serial IO protocols
449 GDB_SERIAL_DEV gdbSerialDevTemplate
= {
450 GDB_SERIAL_DEV_SIGNATURE
,
454 SERIAL_IO_INTERFACE_REVISION
,
456 GdbSerialSetAttributes
,
467 1, // RceiveFifoDepth
475 HARDWARE_DEVICE_PATH
,
478 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
) + sizeof (UINT32
)),
479 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
) + sizeof (UINT32
)) >> 8)
482 EFI_SERIAL_IO_PROTOCOL_GUID
486 END_DEVICE_PATH_TYPE
,
487 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
489 (UINT8
) (sizeof (EFI_DEVICE_PATH_PROTOCOL
)),
490 (UINT8
) (sizeof (EFI_DEVICE_PATH_PROTOCOL
) >> 8)
500 Make two serial consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.
502 These console show up on the remote system running GDB
506 GdbInitializeSerialConsole (
511 GDB_SERIAL_DEV
*StdOutSerialDev
;
512 GDB_SERIAL_DEV
*StdErrSerialDev
;
514 // Use the template to make a copy of the Serial Console private data structure.
515 StdOutSerialDev
= AllocateCopyPool (sizeof (GDB_SERIAL_DEV
), &gdbSerialDevTemplate
);
516 ASSERT (StdOutSerialDev
!= NULL
);
518 // Fixup pointer after the copy
519 StdOutSerialDev
->SerialIo
.Mode
= &StdOutSerialDev
->SerialMode
;
521 StdErrSerialDev
= AllocateCopyPool (sizeof (GDB_SERIAL_DEV
), &gdbSerialDevTemplate
);
522 ASSERT (StdErrSerialDev
!= NULL
);
524 // Fixup pointer and modify stuff that is different for StdError
525 StdErrSerialDev
->SerialIo
.Mode
= &StdErrSerialDev
->SerialMode
;
526 StdErrSerialDev
->DevicePath
.Index
= 1;
527 StdErrSerialDev
->OutFileDescriptor
= GDB_STDERR
;
529 // Make a new handle with Serial IO protocol and its device path on it.
530 Status
= gBS
->InstallMultipleProtocolInterfaces (
531 &StdOutSerialDev
->Handle
,
532 &gEfiSerialIoProtocolGuid
, &StdOutSerialDev
->SerialIo
,
533 &gEfiDevicePathProtocolGuid
, &StdOutSerialDev
->DevicePath
,
536 ASSERT_EFI_ERROR (Status
);
538 // Make a new handle with Serial IO protocol and its device path on it.
539 Status
= gBS
->InstallMultipleProtocolInterfaces (
540 &StdErrSerialDev
->Handle
,
541 &gEfiSerialIoProtocolGuid
, &StdErrSerialDev
->SerialIo
,
542 &gEfiDevicePathProtocolGuid
, &StdErrSerialDev
->DevicePath
,
545 ASSERT_EFI_ERROR (Status
);