]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmbeddedPkg/GdbStub/SerialIo.c
BaseTools/Capsule: Do not support -o with --dump-info
[mirror_edk2.git] / EmbeddedPkg / GdbStub / SerialIo.c
index 5afaed06b9fccfe0c3e7239040b081881b44498b..32ceaf1233b9da97f304a320862dac91844287c7 100644 (file)
-/** @file
-  Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system 
-  running GDB. One consle for error information and another console for user input/output.
-  
-  Basic packet format is $packet-data#checksum. So every comand has 4 bytes of overhead: $, 
-  #, 0, 0. The 0 and 0 are the ascii characters for the checksum. 
-  
-
-  Copyright (c) 2008-2009, Apple Inc. All rights reserved.
-  
-  All rights reserved. This program and the accompanying materials
-  are licensed and made available under the terms and conditions of the BSD License
-  which accompanies this distribution.  The full text of the license may be found at
-  http://opensource.org/licenses/bsd-license.php
-
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include <GdbStubInternal.h>
-
-//
-// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c
-// here we need to wait for the periodic callback to do this. 
-//
-BOOLEAN gCtrlCBreakFlag = FALSE;
-
-//
-// If the periodic callback is called while we are processing an F packet we need
-// to let the callback know to not read from the serail stream as it could steal
-// characters from the F reponse packet
-//
-BOOLEAN gProcessingFPacket = FALSE;
-
-/**
-  Process a control-C break message. 
-  
-  Currently a place holder, remove the ASSERT when it gets implemented. 
-
-  @param  ErrNo   Error infomration from the F reply packet or other source
-
-**/
-
-VOID
-GdbCtrlCBreakMessage (
-  IN  UINTN ErrNo
-  )
-{
-  // See D.10.5 of gdb.pdf
-  // This should look like a break message. Should look like SIGINT
-
-  /* TODO: Make sure if we should do anything with ErrNo */
-  //Turn on the global Ctrl-C flag.
-  gCtrlCBreakFlag = TRUE;
-}
-
-
-/**
-  Parse the F reply packet and extract the return value and an ErrNo if it exists.
-
-  @param  Packet  Packet to parse like an F reply packet
-  @param  ErrNo   Buffer to hold Count bytes that were read
-
-  @retval -1      Error, not a valid F reply packet 
-  @retval other   Return the return code from the F reply packet 
-
-**/
-INTN
-GdbParseFReplyPacket (
-  IN  CHAR8   *Packet,
-  OUT UINTN   *ErrNo   
-  )
-{
-  INTN   RetCode;
-   
-  if (Packet[0] != 'F') {
-    // A valid responce would be an F packet
-    return -1;
-  }
-  
-  RetCode = AsciiStrHexToUintn (&Packet[1]);
-  
-  // Find 1st comma 
-  for (;*Packet != '\0' && *Packet != ',';  Packet++);  
-  if (*Packet == '\0') {
-    *ErrNo = 0;
-    return RetCode;
-  }
-  
-  *ErrNo = AsciiStrHexToUintn (++Packet);
-
-  // Find 2nd comma 
-  for (;*Packet != '\0' && *Packet != ',';  Packet++);  
-  if (*Packet == '\0') {
-    return RetCode;
-  }
-  
-  if (*(++Packet) == 'C') {
-    GdbCtrlCBreakMessage (*ErrNo);  
-  }
-  
-  return RetCode;
-}
-
-
-/**
-  Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates 
-  the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.
-
-  @param  FileDescriptor   Device to talk to.
-  @param  Buffer           Buffer to hold Count bytes that were read
-  @param  Count            Number of bytes to transfer. 
-
-  @retval -1               Error
-  @retval {other}          Number of bytes read.
-
-**/
-INTN
-GdbRead (
-  IN  INTN    FileDescriptor,
-  OUT VOID    *Buffer,
-  IN  UINTN   Count
-  )
-{
-  CHAR8   Packet[128];
-  UINTN   Size;
-  INTN    RetCode;
-  UINTN   ErrNo;
-  BOOLEAN ReceiveDone = FALSE;
-   
-  // Send:
-  // "Fread,XX,YYYYYYYY,XX
-  //
-  // XX - FileDescriptor in ASCII
-  // YYYYYYYY - Buffer address in ASCII 
-  // XX - Count in ASCII
-  // SS - check sum
-  //
-  Size = AsciiSPrint (Packet, sizeof (Packet), "Fread,%x,%x,%x", FileDescriptor, Buffer, Count);
-  // Packet array is too small if you got this ASSERT
-  ASSERT (Size < sizeof (Packet));
-  
-  gProcessingFPacket = TRUE;
-  SendPacket (Packet);
-  Print ((CHAR16 *)L"Packet sent..\n");
-
-  do {
-    // Reply:
-    ReceivePacket (Packet, sizeof (Packet));
-    Print ((CHAR16 *)L"Command received..%c\n", Packet[0]);
-
-    // Process GDB commands
-    switch (Packet[0]) {
-      //Write memory command.
-      //M addr,length:XX...
-      case    'M':
-        WriteToMemory (Packet);
-        break;
-
-      //Fretcode, errno, Ctrl-C flag
-      //retcode - Count read
-      case    'F':
-        //Once target receives F reply packet that means the previous
-        //transactions are finished.
-        ReceiveDone = TRUE;
-        break;
-
-      //Send empty buffer
-      default    :
-        SendNotSupported();
-        break;
-    }
-  } while (ReceiveDone == FALSE);
-
-  RetCode = GdbParseFReplyPacket (Packet, &ErrNo);
-  Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo);
-  
-  if (ErrNo > 0) {
-    //Send error to the host if there is any.
-    SendError ((UINT8)ErrNo);
-  }
-  
-  gProcessingFPacket = FALSE;
-
-  return RetCode;
-}  
-  
-
-/**
-  Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates 
-  nothing was written. On error -1 is returned. 
-
-  @param  FileDescriptor   Device to talk to.
-  @param  Buffer           Buffer to hold Count bytes that are to be written
-  @param  Count            Number of bytes to transfer. 
-
-  @retval -1               Error
-  @retval {other}          Number of bytes written.
-
-**/
-INTN
-GdbWrite (
-  IN  INTN          FileDescriptor,
-  OUT CONST VOID    *Buffer,
-  IN  UINTN         Count
-  )
-{
-  CHAR8   Packet[128];
-  UINTN   Size;
-  INTN    RetCode;
-  UINTN   ErrNo;
-  BOOLEAN ReceiveDone = FALSE;
-
-  // Send:
-  // #Fwrite,XX,YYYYYYYY,XX$SS
-  //
-  // XX - FileDescriptor in ASCII
-  // YYYYYYYY - Buffer address in ASCII 
-  // XX - Count in ASCII
-  // SS - check sum
-  //
-  Size = AsciiSPrint (Packet, sizeof (Packet), "Fwrite,%x,%x,%x", FileDescriptor, Buffer, Count);
-  // Packet array is too small if you got this ASSERT
-  ASSERT (Size < sizeof (Packet));
-  
-  SendPacket (Packet);
-  Print ((CHAR16 *)L"Packet sent..\n");
-
-  do {
-    // Reply:
-    ReceivePacket (Packet, sizeof (Packet));
-    Print ((CHAR16 *)L"Command received..%c\n", Packet[0]);
-
-    // Process GDB commands
-    switch (Packet[0]) {
-      //Read memory command.
-      //m addr,length. 
-      case    'm':
-        ReadFromMemory (Packet);
-        break;
-
-      //Fretcode, errno, Ctrl-C flag
-      //retcode - Count read
-      case    'F':
-        //Once target receives F reply packet that means the previous 
-        //transactions are finished.
-        ReceiveDone = TRUE;
-        break;
-      
-      //Send empty buffer
-      default    :  
-        SendNotSupported();
-        break;
-    }
-  } while (ReceiveDone == FALSE);
-
-  RetCode = GdbParseFReplyPacket (Packet, &ErrNo);
-  Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo);
-
-  //Send error to the host if there is any.
-  if (ErrNo > 0) {
-    SendError((UINT8)ErrNo);
-  }
-  return RetCode;
-}
-
-
-/**
-  Reset the serial device.
-
-  @param  This              Protocol instance pointer.
-                            
-  @retval EFI_SUCCESS       The device was reset.
-  @retval EFI_DEVICE_ERROR  The serial device could not be reset.
-
-**/
-EFI_STATUS
-EFIAPI
-GdbSerialReset (
-  IN EFI_SERIAL_IO_PROTOCOL  *This
-  )
-{
-  return EFI_SUCCESS;
-}
-
-
-/**
-  Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, 
-  data buts, and stop bits on a serial device.
-
-  @param  This             Protocol instance pointer.
-  @param  BaudRate         The requested baud rate. A BaudRate value of 0 will use the the
-                           device's default interface speed.
-  @param  ReveiveFifoDepth The requested depth of the FIFO on the receive side of the
-                           serial interface. A ReceiveFifoDepth value of 0 will use
-                           the device's dfault FIFO depth.
-  @param  Timeout          The requested time out for a single character in microseconds.
-                           This timeout applies to both the transmit and receive side of the
-                           interface. A Timeout value of 0 will use the device's default time
-                           out value.
-  @param  Parity           The type of parity to use on this serial device. A Parity value of
-                           DefaultParity will use the device's default parity value.
-  @param  DataBits         The number of data bits to use on the serial device. A DataBits
-                           vaule of 0 will use the device's default data bit setting.
-  @param  StopBits         The number of stop bits to use on this serial device. A StopBits
-                           value of DefaultStopBits will use the device's default number of
-                           stop bits.
-
-  @retval EFI_SUCCESS      The device was reset.
-  @retval EFI_DEVICE_ERROR The serial device could not be reset.
-
-**/
-EFI_STATUS
-EFIAPI
-GdbSerialSetAttributes (
-  IN EFI_SERIAL_IO_PROTOCOL  *This,
-  IN UINT64                  BaudRate,
-  IN UINT32                  ReceiveFifoDepth,
-  IN UINT32                  Timeout,
-  IN EFI_PARITY_TYPE         Parity,
-  IN UINT8                   DataBits,
-  IN EFI_STOP_BITS_TYPE      StopBits
-  )
-{
-  return EFI_UNSUPPORTED;
-}
-
-
-/**
-  Set the control bits on a serial device
-
-  @param  This             Protocol instance pointer.
-  @param  Control          Set the bits of Control that are settable.
-
-  @retval EFI_SUCCESS      The new control bits were set on the serial device.
-  @retval EFI_UNSUPPORTED  The serial device does not support this operation.
-  @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
-
-**/
-EFI_STATUS
-EFIAPI
-GdbSerialSetControl (
-  IN EFI_SERIAL_IO_PROTOCOL  *This,
-  IN UINT32                  Control
-  )
-{
-  return EFI_UNSUPPORTED;
-}
-
-
-/**
-  Retrieves the status of thecontrol bits on a serial device
-
-  @param  This              Protocol instance pointer.
-  @param  Control           A pointer to return the current Control signals from the serial device.
-                            
-  @retval EFI_SUCCESS       The control bits were read from the serial device.
-  @retval EFI_DEVICE_ERROR  The serial device is not functioning correctly.
-
-**/
-EFI_STATUS
-EFIAPI
-GdbSerialGetControl (
-  IN EFI_SERIAL_IO_PROTOCOL  *This,
-  OUT UINT32                 *Control
-  )
-{
-  return EFI_UNSUPPORTED;
-}
-
-
-/**
-  Writes data to a serial device.
-
-  @param  This              Protocol instance pointer.
-  @param  BufferSize        On input, the size of the Buffer. On output, the amount of
-                            data actually written.
-  @param  Buffer            The buffer of data to write
-
-  @retval EFI_SUCCESS       The data was written.
-  @retval EFI_DEVICE_ERROR  The device reported an error.
-  @retval EFI_TIMEOUT       The data write was stopped due to a timeout.
-
-**/
-EFI_STATUS
-EFIAPI
-GdbSerialWrite (
-  IN EFI_SERIAL_IO_PROTOCOL  *This,
-  IN OUT UINTN               *BufferSize,
-  IN VOID                    *Buffer
-  )
-{
-  GDB_SERIAL_DEV  *SerialDev;
-  UINTN            Return;
-
-  SerialDev = GDB_SERIAL_DEV_FROM_THIS (This);
-  
-  Return = GdbWrite (SerialDev->OutFileDescriptor, Buffer, *BufferSize);
-  if (Return == (UINTN)-1) {
-    return EFI_DEVICE_ERROR;
-  }
-  
-  if (Return != *BufferSize) {
-    *BufferSize = Return;
-  }
-  
-  return EFI_SUCCESS;
-}
-
-/**
-  Writes data to a serial device.
-
-  @param  This              Protocol instance pointer.
-  @param  BufferSize        On input, the size of the Buffer. On output, the amount of
-                            data returned in Buffer.
-  @param  Buffer            The buffer to return the data into.
-
-  @retval EFI_SUCCESS       The data was read.
-  @retval EFI_DEVICE_ERROR  The device reported an error.
-  @retval EFI_TIMEOUT       The data write was stopped due to a timeout.
-
-**/
-
-EFI_STATUS
-EFIAPI
-GdbSerialRead (
-  IN EFI_SERIAL_IO_PROTOCOL  *This,
-  IN OUT UINTN               *BufferSize,
-  OUT VOID                   *Buffer
-  )
-{
-  GDB_SERIAL_DEV  *SerialDev;
-  UINTN            Return;
-
-  SerialDev = GDB_SERIAL_DEV_FROM_THIS (This);
-  
-  Return = GdbRead (SerialDev->InFileDescriptor, Buffer, *BufferSize);
-  if (Return == (UINTN)-1) {
-    return EFI_DEVICE_ERROR;
-  }
-  
-  if (Return != *BufferSize) {
-    *BufferSize = Return;
-  }
-  
-  return EFI_SUCCESS;
-}
-
-
-// 
-// Template used to initailize the GDB Serial IO protocols
-//
-GDB_SERIAL_DEV gdbSerialDevTemplate = {
-  GDB_SERIAL_DEV_SIGNATURE,
-  NULL,
-  
-  { // SerialIo
-    SERIAL_IO_INTERFACE_REVISION,
-    GdbSerialReset,
-    GdbSerialSetAttributes,
-    GdbSerialSetControl,
-    GdbSerialGetControl,
-    GdbSerialWrite,
-    GdbSerialRead,
-    NULL
-  },
-  { // SerialMode
-    0,      // ControlMask
-    0,      // Timeout
-    0,      // BaudRate
-    1,      // RceiveFifoDepth
-    0,      // DataBits
-    0,      // Parity
-    0       // StopBits
-  },
-  { 
-    {
-      HARDWARE_DEVICE_PATH,
-      HW_VENDOR_DP,
-      {
-        (UINT8) (sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)),
-        (UINT8) ((sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)) >> 8)
-      },
-      EFI_SERIAL_IO_PROTOCOL_GUID,
-    },
-    0,
-    {
-      END_DEVICE_PATH_TYPE,
-      END_ENTIRE_DEVICE_PATH_SUBTYPE,
-      {
-        (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),
-        (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL) >> 8)
-      }
-    },
-  },
-  GDB_STDIN,
-  GDB_STDOUT
-};
-
-
-/**
-  Make two serial consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.
-  
-  These console show up on the remote system running GDB
-
-**/
-VOID
-GdbInitializeSerialConsole (
-  VOID
-  )
-{
-  EFI_STATUS      Status;
-  GDB_SERIAL_DEV  *StdOutSerialDev;
-  GDB_SERIAL_DEV  *StdErrSerialDev;
-
-  // Use the template to make a copy of the Serial Console private data structure.
-  StdOutSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV),  &gdbSerialDevTemplate);
-  ASSERT (StdOutSerialDev != NULL);
-  
-  // Fixup pointer after the copy
-  StdOutSerialDev->SerialIo.Mode = &StdOutSerialDev->SerialMode;
-  
-  StdErrSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV),  &gdbSerialDevTemplate);
-  ASSERT (StdErrSerialDev != NULL);
-
-  // Fixup pointer and modify stuff that is different for StdError
-  StdErrSerialDev->SerialIo.Mode = &StdErrSerialDev->SerialMode;  
-  StdErrSerialDev->DevicePath.Index = 1;
-  StdErrSerialDev->OutFileDescriptor = GDB_STDERR;
-  
-  // Make a new handle with Serial IO protocol and its device path on it.
-  Status = gBS->InstallMultipleProtocolInterfaces (
-                  &StdOutSerialDev->Handle, 
-                  &gEfiSerialIoProtocolGuid,   &StdOutSerialDev->SerialIo,
-                  &gEfiDevicePathProtocolGuid, &StdOutSerialDev->DevicePath,
-                  NULL
-                  );
-  ASSERT_EFI_ERROR (Status);
-
-  // Make a new handle with Serial IO protocol and its device path on it.
-  Status = gBS->InstallMultipleProtocolInterfaces (
-                  &StdErrSerialDev->Handle, 
-                  &gEfiSerialIoProtocolGuid,   &StdErrSerialDev->SerialIo,
-                  &gEfiDevicePathProtocolGuid, &StdErrSerialDev->DevicePath,
-                  NULL
-                  );
-  ASSERT_EFI_ERROR (Status);
-}
-
+/** @file\r
+  Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system\r
+  running GDB. One consle for error information and another console for user input/output.\r
+\r
+  Basic packet format is $packet-data#checksum. So every comand has 4 bytes of overhead: $,\r
+  #, 0, 0. The 0 and 0 are the ascii characters for the checksum.\r
+\r
+\r
+  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <GdbStubInternal.h>\r
+\r
+//\r
+// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c\r
+// here we need to wait for the periodic callback to do this.\r
+//\r
+BOOLEAN gCtrlCBreakFlag = FALSE;\r
+\r
+//\r
+// If the periodic callback is called while we are processing an F packet we need\r
+// to let the callback know to not read from the serail stream as it could steal\r
+// characters from the F reponse packet\r
+//\r
+BOOLEAN gProcessingFPacket = FALSE;\r
+\r
+/**\r
+  Process a control-C break message.\r
+\r
+  Currently a place holder, remove the ASSERT when it gets implemented.\r
+\r
+  @param  ErrNo   Error infomration from the F reply packet or other source\r
+\r
+**/\r
+\r
+VOID\r
+GdbCtrlCBreakMessage (\r
+  IN  UINTN ErrNo\r
+  )\r
+{\r
+  // See D.10.5 of gdb.pdf\r
+  // This should look like a break message. Should look like SIGINT\r
+\r
+  /* TODO: Make sure if we should do anything with ErrNo */\r
+  //Turn on the global Ctrl-C flag.\r
+  gCtrlCBreakFlag = TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Parse the F reply packet and extract the return value and an ErrNo if it exists.\r
+\r
+  @param  Packet  Packet to parse like an F reply packet\r
+  @param  ErrNo   Buffer to hold Count bytes that were read\r
+\r
+  @retval -1      Error, not a valid F reply packet\r
+  @retval other   Return the return code from the F reply packet\r
+\r
+**/\r
+INTN\r
+GdbParseFReplyPacket (\r
+  IN  CHAR8   *Packet,\r
+  OUT UINTN   *ErrNo\r
+  )\r
+{\r
+  INTN   RetCode;\r
+\r
+  if (Packet[0] != 'F') {\r
+    // A valid responce would be an F packet\r
+    return -1;\r
+  }\r
+\r
+  RetCode = AsciiStrHexToUintn (&Packet[1]);\r
+\r
+  // Find 1st comma\r
+  for (;*Packet != '\0' && *Packet != ',';  Packet++);\r
+  if (*Packet == '\0') {\r
+    *ErrNo = 0;\r
+    return RetCode;\r
+  }\r
+\r
+  *ErrNo = AsciiStrHexToUintn (++Packet);\r
+\r
+  // Find 2nd comma\r
+  for (;*Packet != '\0' && *Packet != ',';  Packet++);\r
+  if (*Packet == '\0') {\r
+    return RetCode;\r
+  }\r
+\r
+  if (*(++Packet) == 'C') {\r
+    GdbCtrlCBreakMessage (*ErrNo);\r
+  }\r
+\r
+  return RetCode;\r
+}\r
+\r
+\r
+/**\r
+  Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates\r
+  the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.\r
+\r
+  @param  FileDescriptor   Device to talk to.\r
+  @param  Buffer           Buffer to hold Count bytes that were read\r
+  @param  Count            Number of bytes to transfer.\r
+\r
+  @retval -1               Error\r
+  @retval {other}          Number of bytes read.\r
+\r
+**/\r
+INTN\r
+GdbRead (\r
+  IN  INTN    FileDescriptor,\r
+  OUT VOID    *Buffer,\r
+  IN  UINTN   Count\r
+  )\r
+{\r
+  CHAR8   Packet[128];\r
+  UINTN   Size;\r
+  INTN    RetCode;\r
+  UINTN   ErrNo;\r
+  BOOLEAN ReceiveDone = FALSE;\r
+\r
+  // Send:\r
+  // "Fread,XX,YYYYYYYY,XX\r
+  //\r
+  // XX - FileDescriptor in ASCII\r
+  // YYYYYYYY - Buffer address in ASCII\r
+  // XX - Count in ASCII\r
+  // SS - check sum\r
+  //\r
+  Size = AsciiSPrint (Packet, sizeof (Packet), "Fread,%x,%x,%x", FileDescriptor, Buffer, Count);\r
+  // Packet array is too small if you got this ASSERT\r
+  ASSERT (Size < sizeof (Packet));\r
+\r
+  gProcessingFPacket = TRUE;\r
+  SendPacket (Packet);\r
+  Print ((CHAR16 *)L"Packet sent..\n");\r
+\r
+  do {\r
+    // Reply:\r
+    ReceivePacket (Packet, sizeof (Packet));\r
+    Print ((CHAR16 *)L"Command received..%c\n", Packet[0]);\r
+\r
+    // Process GDB commands\r
+    switch (Packet[0]) {\r
+      //Write memory command.\r
+      //M addr,length:XX...\r
+      case    'M':\r
+        WriteToMemory (Packet);\r
+        break;\r
+\r
+      //Fretcode, errno, Ctrl-C flag\r
+      //retcode - Count read\r
+      case    'F':\r
+        //Once target receives F reply packet that means the previous\r
+        //transactions are finished.\r
+        ReceiveDone = TRUE;\r
+        break;\r
+\r
+      //Send empty buffer\r
+      default    :\r
+        SendNotSupported();\r
+        break;\r
+    }\r
+  } while (ReceiveDone == FALSE);\r
+\r
+  RetCode = GdbParseFReplyPacket (Packet, &ErrNo);\r
+  Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo);\r
+\r
+  if (ErrNo > 0) {\r
+    //Send error to the host if there is any.\r
+    SendError ((UINT8)ErrNo);\r
+  }\r
+\r
+  gProcessingFPacket = FALSE;\r
+\r
+  return RetCode;\r
+}\r
+\r
+\r
+/**\r
+  Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates\r
+  nothing was written. On error -1 is returned.\r
+\r
+  @param  FileDescriptor   Device to talk to.\r
+  @param  Buffer           Buffer to hold Count bytes that are to be written\r
+  @param  Count            Number of bytes to transfer.\r
+\r
+  @retval -1               Error\r
+  @retval {other}          Number of bytes written.\r
+\r
+**/\r
+INTN\r
+GdbWrite (\r
+  IN  INTN          FileDescriptor,\r
+  OUT CONST VOID    *Buffer,\r
+  IN  UINTN         Count\r
+  )\r
+{\r
+  CHAR8   Packet[128];\r
+  UINTN   Size;\r
+  INTN    RetCode;\r
+  UINTN   ErrNo;\r
+  BOOLEAN ReceiveDone = FALSE;\r
+\r
+  // Send:\r
+  // #Fwrite,XX,YYYYYYYY,XX$SS\r
+  //\r
+  // XX - FileDescriptor in ASCII\r
+  // YYYYYYYY - Buffer address in ASCII\r
+  // XX - Count in ASCII\r
+  // SS - check sum\r
+  //\r
+  Size = AsciiSPrint (Packet, sizeof (Packet), "Fwrite,%x,%x,%x", FileDescriptor, Buffer, Count);\r
+  // Packet array is too small if you got this ASSERT\r
+  ASSERT (Size < sizeof (Packet));\r
+\r
+  SendPacket (Packet);\r
+  Print ((CHAR16 *)L"Packet sent..\n");\r
+\r
+  do {\r
+    // Reply:\r
+    ReceivePacket (Packet, sizeof (Packet));\r
+    Print ((CHAR16 *)L"Command received..%c\n", Packet[0]);\r
+\r
+    // Process GDB commands\r
+    switch (Packet[0]) {\r
+      //Read memory command.\r
+      //m addr,length.\r
+      case    'm':\r
+        ReadFromMemory (Packet);\r
+        break;\r
+\r
+      //Fretcode, errno, Ctrl-C flag\r
+      //retcode - Count read\r
+      case    'F':\r
+        //Once target receives F reply packet that means the previous\r
+        //transactions are finished.\r
+        ReceiveDone = TRUE;\r
+        break;\r
+\r
+      //Send empty buffer\r
+      default    :\r
+        SendNotSupported();\r
+        break;\r
+    }\r
+  } while (ReceiveDone == FALSE);\r
+\r
+  RetCode = GdbParseFReplyPacket (Packet, &ErrNo);\r
+  Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo);\r
+\r
+  //Send error to the host if there is any.\r
+  if (ErrNo > 0) {\r
+    SendError((UINT8)ErrNo);\r
+  }\r
+\r
+  return RetCode;\r
+}\r
+\r
+\r
+/**\r
+  Reset the serial device.\r
+\r
+  @param  This              Protocol instance pointer.\r
+\r
+  @retval EFI_SUCCESS       The device was reset.\r
+  @retval EFI_DEVICE_ERROR  The serial device could not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GdbSerialReset (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,\r
+  data buts, and stop bits on a serial device.\r
+\r
+  @param  This             Protocol instance pointer.\r
+  @param  BaudRate         The requested baud rate. A BaudRate value of 0 will use the the\r
+                           device's default interface speed.\r
+  @param  ReveiveFifoDepth The requested depth of the FIFO on the receive side of the\r
+                           serial interface. A ReceiveFifoDepth value of 0 will use\r
+                           the device's dfault FIFO depth.\r
+  @param  Timeout          The requested time out for a single character in microseconds.\r
+                           This timeout applies to both the transmit and receive side of the\r
+                           interface. A Timeout value of 0 will use the device's default time\r
+                           out value.\r
+  @param  Parity           The type of parity to use on this serial device. A Parity value of\r
+                           DefaultParity will use the device's default parity value.\r
+  @param  DataBits         The number of data bits to use on the serial device. A DataBits\r
+                           vaule of 0 will use the device's default data bit setting.\r
+  @param  StopBits         The number of stop bits to use on this serial device. A StopBits\r
+                           value of DefaultStopBits will use the device's default number of\r
+                           stop bits.\r
+\r
+  @retval EFI_SUCCESS      The device was reset.\r
+  @retval EFI_DEVICE_ERROR The serial device could not be reset.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GdbSerialSetAttributes (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN UINT64                  BaudRate,\r
+  IN UINT32                  ReceiveFifoDepth,\r
+  IN UINT32                  Timeout,\r
+  IN EFI_PARITY_TYPE         Parity,\r
+  IN UINT8                   DataBits,\r
+  IN EFI_STOP_BITS_TYPE      StopBits\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+  Set the control bits on a serial device\r
+\r
+  @param  This             Protocol instance pointer.\r
+  @param  Control          Set the bits of Control that are settable.\r
+\r
+  @retval EFI_SUCCESS      The new control bits were set on the serial device.\r
+  @retval EFI_UNSUPPORTED  The serial device does not support this operation.\r
+  @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GdbSerialSetControl (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN UINT32                  Control\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+  Retrieves the status of thecontrol bits on a serial device\r
+\r
+  @param  This              Protocol instance pointer.\r
+  @param  Control           A pointer to return the current Control signals from the serial device.\r
+\r
+  @retval EFI_SUCCESS       The control bits were read from the serial device.\r
+  @retval EFI_DEVICE_ERROR  The serial device is not functioning correctly.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GdbSerialGetControl (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  OUT UINT32                 *Control\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+  Writes data to a serial device.\r
+\r
+  @param  This              Protocol instance pointer.\r
+  @param  BufferSize        On input, the size of the Buffer. On output, the amount of\r
+                            data actually written.\r
+  @param  Buffer            The buffer of data to write\r
+\r
+  @retval EFI_SUCCESS       The data was written.\r
+  @retval EFI_DEVICE_ERROR  The device reported an error.\r
+  @retval EFI_TIMEOUT       The data write was stopped due to a timeout.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GdbSerialWrite (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN OUT UINTN               *BufferSize,\r
+  IN VOID                    *Buffer\r
+  )\r
+{\r
+  GDB_SERIAL_DEV  *SerialDev;\r
+  UINTN            Return;\r
+\r
+  SerialDev = GDB_SERIAL_DEV_FROM_THIS (This);\r
+\r
+  Return = GdbWrite (SerialDev->OutFileDescriptor, Buffer, *BufferSize);\r
+  if (Return == (UINTN)-1) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (Return != *BufferSize) {\r
+    *BufferSize = Return;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Writes data to a serial device.\r
+\r
+  @param  This              Protocol instance pointer.\r
+  @param  BufferSize        On input, the size of the Buffer. On output, the amount of\r
+                            data returned in Buffer.\r
+  @param  Buffer            The buffer to return the data into.\r
+\r
+  @retval EFI_SUCCESS       The data was read.\r
+  @retval EFI_DEVICE_ERROR  The device reported an error.\r
+  @retval EFI_TIMEOUT       The data write was stopped due to a timeout.\r
+\r
+**/\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+GdbSerialRead (\r
+  IN EFI_SERIAL_IO_PROTOCOL  *This,\r
+  IN OUT UINTN               *BufferSize,\r
+  OUT VOID                   *Buffer\r
+  )\r
+{\r
+  GDB_SERIAL_DEV  *SerialDev;\r
+  UINTN            Return;\r
+\r
+  SerialDev = GDB_SERIAL_DEV_FROM_THIS (This);\r
+\r
+  Return = GdbRead (SerialDev->InFileDescriptor, Buffer, *BufferSize);\r
+  if (Return == (UINTN)-1) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  if (Return != *BufferSize) {\r
+    *BufferSize = Return;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+//\r
+// Template used to initailize the GDB Serial IO protocols\r
+//\r
+GDB_SERIAL_DEV gdbSerialDevTemplate = {\r
+  GDB_SERIAL_DEV_SIGNATURE,\r
+  NULL,\r
+\r
+  { // SerialIo\r
+    SERIAL_IO_INTERFACE_REVISION,\r
+    GdbSerialReset,\r
+    GdbSerialSetAttributes,\r
+    GdbSerialSetControl,\r
+    GdbSerialGetControl,\r
+    GdbSerialWrite,\r
+    GdbSerialRead,\r
+    NULL\r
+  },\r
+  { // SerialMode\r
+    0,      // ControlMask\r
+    0,      // Timeout\r
+    0,      // BaudRate\r
+    1,      // RceiveFifoDepth\r
+    0,      // DataBits\r
+    0,      // Parity\r
+    0       // StopBits\r
+  },\r
+  {\r
+    {\r
+      {\r
+        HARDWARE_DEVICE_PATH,\r
+        HW_VENDOR_DP,\r
+        {\r
+          (UINT8) (sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)),\r
+          (UINT8) ((sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)) >> 8)\r
+        },\r
+      },\r
+      EFI_SERIAL_IO_PROTOCOL_GUID\r
+    },\r
+    0,\r
+    {\r
+      END_DEVICE_PATH_TYPE,\r
+      END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+      {\r
+        (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),\r
+        (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL) >> 8)\r
+      }\r
+    },\r
+  },\r
+  GDB_STDIN,\r
+  GDB_STDOUT\r
+};\r
+\r
+\r
+/**\r
+  Make two serial consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.\r
+\r
+  These console show up on the remote system running GDB\r
+\r
+**/\r
+VOID\r
+GdbInitializeSerialConsole (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  GDB_SERIAL_DEV  *StdOutSerialDev;\r
+  GDB_SERIAL_DEV  *StdErrSerialDev;\r
+\r
+  // Use the template to make a copy of the Serial Console private data structure.\r
+  StdOutSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV),  &gdbSerialDevTemplate);\r
+  ASSERT (StdOutSerialDev != NULL);\r
+\r
+  // Fixup pointer after the copy\r
+  StdOutSerialDev->SerialIo.Mode = &StdOutSerialDev->SerialMode;\r
+\r
+  StdErrSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV),  &gdbSerialDevTemplate);\r
+  ASSERT (StdErrSerialDev != NULL);\r
+\r
+  // Fixup pointer and modify stuff that is different for StdError\r
+  StdErrSerialDev->SerialIo.Mode = &StdErrSerialDev->SerialMode;\r
+  StdErrSerialDev->DevicePath.Index = 1;\r
+  StdErrSerialDev->OutFileDescriptor = GDB_STDERR;\r
+\r
+  // Make a new handle with Serial IO protocol and its device path on it.\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &StdOutSerialDev->Handle,\r
+                  &gEfiSerialIoProtocolGuid,   &StdOutSerialDev->SerialIo,\r
+                  &gEfiDevicePathProtocolGuid, &StdOutSerialDev->DevicePath,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  // Make a new handle with Serial IO protocol and its device path on it.\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &StdErrSerialDev->Handle,\r
+                  &gEfiSerialIoProtocolGuid,   &StdErrSerialDev->SerialIo,\r
+                  &gEfiDevicePathProtocolGuid, &StdErrSerialDev->DevicePath,\r
+                  NULL\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+}\r
+\r