]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/SerialIo.c
This revision can only work with Intel(c) UDK Debugger Tool version 1.3 or greater...
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DxeDebugAgent / SerialIo.c
index 0cb7c5255473ad78055186a91ed65832ac124786..9b181e3ac7fa82cc798c974b6393f8e0f42789be 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Install Serial IO Protocol that layers on top of a Debug Communication Library instance.\r
 \r
-  Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>\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
@@ -149,11 +149,11 @@ SerialRead (
 EFI_SERIAL_IO_MODE  mSerialIoMode = {\r
   SERIAL_PORT_DEFAULT_CONTROL_MASK,\r
   SERIAL_PORT_DEFAULT_TIMEOUT,\r
-  0,  // BaudRate\r
+  0,  // default BaudRate\r
   SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH,\r
-  0,  // DataBits\r
-  0,  // Parity\r
-  0   // StopBits\r
+  0,  // default DataBits\r
+  0,  // default Parity\r
+  0   // default StopBits\r
 };\r
 \r
 //\r
@@ -204,10 +204,10 @@ SERIAL_IO_DEVICE_PATH mSerialIoDevicePath = {
       }\r
     },\r
     0,\r
-    0,  // BaudRate\r
-    0,  // DataBits\r
-    0,  // Parity\r
-    0,  // StopBits\r
+    0,  // default BaudRate\r
+    0,  // default DataBits\r
+    0,  // default Parity\r
+    0,  // default StopBits\r
   },\r
   {\r
     END_DEVICE_PATH_TYPE,\r
@@ -357,34 +357,15 @@ DebugTerminalFifoRemove (
 }\r
 \r
 /**\r
-  Notification function on EFI PCD protocol to install EFI Serial IO protocol based\r
-  on Debug Communication Library. \r
-\r
-  @param[in]  Event    The event of notify protocol.\r
-  @param[in]  Context  Notify event context.\r
+  Install EFI Serial IO protocol based on Debug Communication Library. \r
 \r
 **/\r
 VOID\r
-EFIAPI\r
-InstallSerialIoNotification (\r
-  IN EFI_EVENT     Event,\r
-  IN VOID          *Context\r
+InstallSerialIo (\r
+  VOID\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-\r
-  //\r
-  // Get Debug Port parameters from PCDs\r
-  //\r
-  mSerialIoDevicePath.UartDevicePath.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);\r
-  mSerialIoDevicePath.UartDevicePath.DataBits = PcdGet8 (PcdUartDefaultDataBits);\r
-  mSerialIoDevicePath.UartDevicePath.Parity   = PcdGet8 (PcdUartDefaultParity);\r
-  mSerialIoDevicePath.UartDevicePath.StopBits = PcdGet8 (PcdUartDefaultStopBits);\r
-\r
-  mSerialIoMode.BaudRate = mSerialIoDevicePath.UartDevicePath.BaudRate;\r
-  mSerialIoMode.DataBits = mSerialIoDevicePath.UartDevicePath.DataBits;\r
-  mSerialIoMode.Parity   = mSerialIoDevicePath.UartDevicePath.Parity;\r
-  mSerialIoMode.StopBits = mSerialIoDevicePath.UartDevicePath.StopBits;\r
+  EFI_STATUS       Status;\r
 \r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &mSerialIoHandle,\r
@@ -448,22 +429,10 @@ SerialSetAttributes (
   )\r
 {\r
   //\r
-  // The Debug Communication Library does not support changing communications parameters, so unless\r
-  // the request is to use the default value or the value the Debug Communication Library is already\r
-  // using, then return EFI_INVALID_PARAMETER.\r
+  // The Debug Communication Library CAN NOT change communications parameters (if it has)\r
+  // actually. Because it also has no any idea on what parameters are based on, we cannot\r
+  // check the input parameters (like BaudRate, Parity, DataBits and StopBits). \r
   //\r
-  if (BaudRate != 0 && BaudRate != PcdGet64 (PcdUartDefaultBaudRate)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  if (Parity != DefaultParity && Parity != PcdGet8 (PcdUartDefaultParity)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  if (DataBits != 0 && DataBits != PcdGet8 (PcdUartDefaultDataBits)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-  if (StopBits != DefaultStopBits && StopBits != PcdGet8 (PcdUartDefaultStopBits)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
   \r
   //\r
   // Update the Timeout value in the mode structure based on the request.\r
@@ -536,7 +505,18 @@ SerialGetControl (
   )\r
 {\r
   DEBUG_PORT_HANDLE                Handle;\r
+  BOOLEAN                          DebugTimerInterruptState;\r
+  EFI_TPL                          Tpl;\r
 \r
+  //\r
+  // Raise TPL to prevent recursion from EFI timer interrupts\r
+  //\r
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  \r
+  //\r
+  // Save and disable Debug Timer interrupt to avoid it to access Debug Port\r
+  //\r
+  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
   Handle = GetDebugPortHandle ();\r
   \r
   //\r
@@ -552,6 +532,17 @@ SerialGetControl (
   if (!IsDebugTermianlFifoEmpty (&mSerialFifoForTerminal) || DebugPortPollBuffer (Handle)) {\r
     *Control &= ~EFI_SERIAL_INPUT_BUFFER_EMPTY;\r
   }\r
+\r
+  //\r
+  // Restore Debug Timer interrupt\r
+  //  \r
+  SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);\r
+  \r
+  //\r
+  // Restore to original TPL\r
+  //\r
+  gBS->RestoreTPL (Tpl);\r
+  \r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -577,7 +568,18 @@ SerialWrite (
   )\r
 {\r
   DEBUG_PORT_HANDLE                Handle;\r
+  BOOLEAN                          DebugTimerInterruptState;\r
+  EFI_TPL                          Tpl;\r
 \r
+  //\r
+  // Raise TPL to prevent recursion from EFI timer interrupts\r
+  //\r
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+  \r
+  //\r
+  // Save and disable Debug Timer interrupt to avoid it to access Debug Port\r
+  //\r
+  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
   Handle = GetDebugPortHandle ();\r
   \r
   if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0)  {\r
@@ -593,6 +595,17 @@ SerialWrite (
   } else {\r
     *BufferSize = DebugPortWriteBuffer (Handle, Buffer, *BufferSize);\r
   }\r
+\r
+  //\r
+  // Restore Debug Timer interrupt\r
+  //  \r
+  SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);\r
+  \r
+  //\r
+  // Restore to original TPL\r
+  //\r
+  gBS->RestoreTPL (Tpl);\r
+  \r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -620,17 +633,24 @@ SerialRead (
   EFI_STATUS                  Status;\r
   UINTN                       Index;\r
   UINT8                       *Uint8Buffer;\r
-  BOOLEAN                     OldInterruptState;\r
+  BOOLEAN                     DebugTimerInterruptState;\r
+  EFI_TPL                     Tpl;\r
   DEBUG_PORT_HANDLE           Handle;\r
-  UINT8                       Data;\r
-\r
-  Handle = GetDebugPortHandle ();\r
+  DEBUG_PACKET_HEADER         DebugHeader;\r
+  UINT8                       *Data8;\r
 \r
   //\r
-  // Save and disable Debug Timer interrupt to avoid it to access Debug Port\r
+  // Raise TPL to prevent recursion from EFI timer interrupts\r
   //\r
-  OldInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
+  Tpl = gBS->RaiseTPL (TPL_NOTIFY);\r
   \r
+  //\r
+  // Save and disable Debug Timer interrupt to avoid it to access Debug Port\r
+  //\r
+  DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
+  Handle = GetDebugPortHandle ();\r
\r
+  Data8 = (UINT8 *) &DebugHeader;\r
   Uint8Buffer = (UINT8 *)Buffer;\r
   if ((mSerialIoMode.ControlMask & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) != 0)  {\r
     if ((mLoopbackBuffer & SERIAL_PORT_LOOPBACK_BUFFER_FULL) == 0) {\r
@@ -644,9 +664,9 @@ SerialRead (
       //\r
       // Read input character from terminal FIFO firstly\r
       //\r
-      Status = DebugTerminalFifoRemove (&mSerialFifoForTerminal, &Data);\r
+      Status = DebugTerminalFifoRemove (&mSerialFifoForTerminal, Data8);\r
       if (Status == EFI_SUCCESS) {\r
-        *Uint8Buffer = Data;\r
+        *Uint8Buffer = *Data8;\r
         Uint8Buffer ++;\r
         continue;\r
       }\r
@@ -656,16 +676,25 @@ SerialRead (
       if (!DebugPortPollBuffer (Handle)) {\r
         break;\r
       }\r
-      DebugPortReadBuffer (Handle, &Data, 1, 0);\r
+      DebugPortReadBuffer (Handle, Data8, 1, 0);\r
 \r
-      if (Data== DEBUG_STARTING_SYMBOL_ATTACH ||\r
-          Data == DEBUG_STARTING_SYMBOL_BREAK) {\r
+      if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {\r
         //\r
         // Add the debug symbol into Debug FIFO\r
         //\r
-        DebugTerminalFifoAdd (&mSerialFifoForDebug, Data);\r
+        DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer attach symbol received %x", *Data8);\r
+        DebugTerminalFifoAdd (&mSerialFifoForDebug, *Data8);\r
+      } else if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {\r
+        Status = ReadRemainingBreakPacket (Handle, &DebugHeader);\r
+        if (Status == EFI_SUCCESS) {\r
+          DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Terminal Timer break symbol received %x", DebugHeader.Command);\r
+          DebugTerminalFifoAdd (&mSerialFifoForDebug, DebugHeader.Command);\r
+        }\r
+        if (Status == EFI_TIMEOUT) {\r
+          continue;\r
+        }\r
       } else {\r
-        *Uint8Buffer = Data;\r
+        *Uint8Buffer = *Data8;\r
         Uint8Buffer ++;\r
       }\r
     }\r
@@ -675,7 +704,12 @@ SerialRead (
   //\r
   // Restore Debug Timer interrupt\r
   //  \r
-  SaveAndSetDebugTimerInterrupt (OldInterruptState);\r
+  SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);\r
+  \r
+  //\r
+  // Restore to original TPL\r
+  //\r
+  gBS->RestoreTPL (Tpl);\r
   \r
   return EFI_SUCCESS;\r
 }\r
@@ -691,36 +725,90 @@ SerialRead (
 \r
 **/\r
 EFI_STATUS\r
-DebugReadBreakSymbol (\r
+DebugReadBreakFromDebugPort (\r
   IN  DEBUG_PORT_HANDLE      Handle,\r
   OUT UINT8                  *BreakSymbol\r
   )\r
 {\r
-  EFI_STATUS               Status;\r
-  UINT8                    Data;\r
+  EFI_STATUS                 Status;\r
+  DEBUG_PACKET_HEADER        DebugHeader;\r
+  UINT8                      *Data8;\r
 \r
-  Status = DebugTerminalFifoRemove (&mSerialFifoForDebug, &Data);\r
-  if (Status != EFI_SUCCESS) {\r
+  *BreakSymbol = 0;\r
+  //\r
+  // If Debug Port buffer has data, read it till it was break symbol or Debug Port buffer empty.\r
+  //\r
+  Data8 = (UINT8 *) &DebugHeader;\r
+  while (TRUE) {\r
+    //\r
+    // If start symbol is not received\r
+    //\r
     if (!DebugPortPollBuffer (Handle)) {\r
       //\r
-      // No data in Debug Port buffer.\r
+      // If no data in Debug Port, exit\r
       //\r
-      return EFI_NOT_FOUND;\r
+      break;\r
+    }\r
+    //\r
+    // Try to read the start symbol\r
+    //\r
+    DebugPortReadBuffer (Handle, Data8, 1, 0);\r
+    if (*Data8 == DEBUG_STARTING_SYMBOL_ATTACH) {\r
+      DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer attach symbol received %x", *Data8);\r
+      *BreakSymbol = *Data8;\r
+      return EFI_SUCCESS;\r
+    } \r
+    if (*Data8 == DEBUG_STARTING_SYMBOL_NORMAL) {\r
+      Status = ReadRemainingBreakPacket (Handle, &DebugHeader);\r
+      if (Status == EFI_SUCCESS) {\r
+        DebugAgentMsgPrint (DEBUG_AGENT_INFO, "Debug Timer break symbol received %x", DebugHeader.Command);\r
+        *BreakSymbol = DebugHeader.Command;\r
+        return EFI_SUCCESS;\r
+      }\r
+      if (Status == EFI_TIMEOUT) {\r
+        break;\r
+      }\r
     } else {\r
       //\r
-      // Read one character from Debug Port.\r
+      // Add to Terminal FIFO\r
       //\r
-      DebugPortReadBuffer (Handle, &Data, 1, 0);\r
-      if ((Data != DEBUG_STARTING_SYMBOL_ATTACH) && (Data != DEBUG_STARTING_SYMBOL_BREAK)) {\r
-        //\r
-        // If the data is not Break symbol, add it into Terminal FIFO\r
-        //\r
-        DebugTerminalFifoAdd (&mSerialFifoForTerminal, Data);\r
-        return EFI_NOT_FOUND;\r
-      }\r
+      DebugTerminalFifoAdd (&mSerialFifoForTerminal, *Data8);\r
     }\r
   }\r
   \r
-  *BreakSymbol = Data;\r
-  return EFI_SUCCESS;\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Read the Attach/Break-in symbols.\r
+\r
+  @param[in]  Handle         Pointer to Debug Port handle.\r
+  @param[out] BreakSymbol    Returned break symbol.\r
+\r
+  @retval EFI_SUCCESS        Read the symbol in BreakSymbol.\r
+  @retval EFI_NOT_FOUND      No read the break symbol.\r
+\r
+**/\r
+EFI_STATUS\r
+DebugReadBreakSymbol (\r
+  IN  DEBUG_PORT_HANDLE      Handle,\r
+  OUT UINT8                  *BreakSymbol\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  UINT8                    Data8;\r
+\r
+  //\r
+  // Read break symbol from debug FIFO firstly\r
+  //\r
+  Status = DebugTerminalFifoRemove (&mSerialFifoForDebug, &Data8);\r
+  if (Status == EFI_SUCCESS) {\r
+    *BreakSymbol = Data8;\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    //\r
+    // Read Break symbol from debug port\r
+    //\r
+    return DebugReadBreakFromDebugPort (Handle, BreakSymbol);\r
+  }\r
 }\r