Current implementation executes key notify function in TimerHandler
at TPL_NOTIFY. The code change is to make key notify function
executed at TPL_CALLBACK to reduce the time occupied at TPL_NOTIFY.

The code will signal KeyNotify process event if the key pressed
matches any key registered and insert the KeyData to the EFI Key
queue for notify, then the KeyNotify process handler will invoke
key notify functions at TPL_CALLBACK.

Cc: Ruiyu Ni <ruiyu...@intel.com>
Cc: Michael Kinney <michael.d.kin...@intel.com>
Cc: Feng Tian <feng.t...@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.z...@intel.com>
---
 .../Universal/Console/TerminalDxe/Terminal.c       |  25 ++-
 .../Universal/Console/TerminalDxe/Terminal.h       |  80 +++++++++-
 .../Universal/Console/TerminalDxe/TerminalConIn.c  | 177 ++++++++++++++++++++-
 3 files changed, 275 insertions(+), 7 deletions(-)

diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c 
b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
index 3f445f02721f..a209bf3cacf8 100644
--- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
+++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
@@ -2,7 +2,7 @@
   Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and
   Simple Text Output Protocol upon Serial IO Protocol.
 
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
 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
@@ -75,6 +75,7 @@ TERMINAL_DEV  mTerminalDevTemplate = {
   NULL, // RawFifo
   NULL, // UnicodeFiFo
   NULL, // EfiKeyFiFo
+  NULL, // EfiKeyFiFoForNotify
 
   NULL, // ControllerNameTable
   NULL, // TimerEvent
@@ -99,7 +100,8 @@ TERMINAL_DEV  mTerminalDevTemplate = {
   {   // NotifyList
     NULL,
     NULL,
-  }
+  },
+  NULL // KeyNotifyProcessEvent
 };
 
 TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {
@@ -791,6 +793,10 @@ TerminalDriverBindingStart (
     if (TerminalDevice->EfiKeyFiFo == NULL) {
       goto Error;
     }
+    TerminalDevice->EfiKeyFiFoForNotify = AllocateZeroPool (sizeof 
(EFI_KEY_FIFO));
+    if (TerminalDevice->EfiKeyFiFoForNotify == NULL) {
+      goto Error;
+    }
 
     //
     // Set the timeout value of serial buffer for
@@ -1000,6 +1006,15 @@ TerminalDriverBindingStart (
                     );
     ASSERT_EFI_ERROR (Status);
 
+    Status = gBS->CreateEvent (
+                    EVT_NOTIFY_SIGNAL,
+                    TPL_CALLBACK,
+                    KeyNotifyProcessHandler,
+                    TerminalDevice,
+                    &TerminalDevice->KeyNotifyProcessEvent
+                    );
+    ASSERT_EFI_ERROR (Status);
+
     Status = gBS->InstallProtocolInterface (
                     &TerminalDevice->Handle,
                     &gEfiDevicePathProtocolGuid,
@@ -1222,7 +1237,10 @@ Error:
       if (TerminalDevice->EfiKeyFiFo != NULL) {
         FreePool (TerminalDevice->EfiKeyFiFo);
       }
-
+      if (TerminalDevice->EfiKeyFiFoForNotify != NULL) {
+        FreePool (TerminalDevice->EfiKeyFiFoForNotify);
+      }
+  
       if (TerminalDevice->ControllerNameTable != NULL) {
         FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);
       }
@@ -1400,6 +1418,7 @@ TerminalDriverBindingStop (
         gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);
         gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);
         gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);
+        gBS->CloseEvent (TerminalDevice->KeyNotifyProcessEvent);
         TerminalFreeNotifyList (&TerminalDevice->NotifyList);
         FreePool (TerminalDevice->DevicePath);
         if (TerminalDevice->TerminalConsoleModeData != NULL) {
diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h 
b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
index 3ee396984e6a..e16b89c264ce 100644
--- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
+++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
@@ -1,7 +1,7 @@
 /** @file
   Header file for Terminal driver.
 
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
 Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD 
License
@@ -95,6 +95,7 @@ typedef struct {
   RAW_DATA_FIFO                       *RawFiFo;
   UNICODE_FIFO                        *UnicodeFiFo;
   EFI_KEY_FIFO                        *EfiKeyFiFo;
+  EFI_KEY_FIFO                        *EfiKeyFiFoForNotify;
   EFI_UNICODE_STRING_TABLE            *ControllerNameTable;
   EFI_EVENT                           TimerEvent;
   EFI_EVENT                           TwoSecondTimeOut;
@@ -113,6 +114,7 @@ typedef struct {
   BOOLEAN                             OutputEscChar;
   EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL   SimpleInputEx;
   LIST_ENTRY                          NotifyList;
+  EFI_EVENT                           KeyNotifyProcessEvent;
 } TERMINAL_DEV;
 
 #define INPUT_STATE_DEFAULT               0x00
@@ -944,6 +946,67 @@ IsRawFiFoFull (
 /**
   Insert one pre-fetched key into the FIFO buffer.
 
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
+  @param  Input                 The key will be input.
+
+  @retval TRUE                  If insert successfully.
+  @retval FALSE                 If FIFO buffer is full before key insertion,
+                                and the key is lost.
+
+**/
+BOOLEAN
+EfiKeyFiFoForNotifyInsertOneKey (
+  EFI_KEY_FIFO                  *EfiKeyFiFo,
+  EFI_INPUT_KEY                 *Input
+  );
+
+/**
+  Remove one pre-fetched key out of the FIFO buffer.
+
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
+  @param  Output                The key will be removed.
+
+  @retval TRUE                  If insert successfully.
+  @retval FALSE                 If FIFO buffer is empty before remove 
operation.
+
+**/
+BOOLEAN
+EfiKeyFiFoForNotifyRemoveOneKey (
+  EFI_KEY_FIFO                  *EfiKeyFiFo,
+  EFI_INPUT_KEY                 *Output
+  );
+
+/**
+  Clarify whether FIFO buffer is empty.
+
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
+
+  @retval TRUE                  If FIFO buffer is empty.
+  @retval FALSE                 If FIFO buffer is not empty.
+
+**/
+BOOLEAN
+IsEfiKeyFiFoForNotifyEmpty (
+  IN EFI_KEY_FIFO               *EfiKeyFiFo
+  );
+
+/**
+  Clarify whether FIFO buffer is full.
+
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
+
+  @retval TRUE                  If FIFO buffer is full.
+  @retval FALSE                 If FIFO buffer is not full.
+
+**/
+BOOLEAN
+IsEfiKeyFiFoForNotifyFull (
+  EFI_KEY_FIFO                  *EfiKeyFiFo
+  );
+
+/**
+  Insert one pre-fetched key into the FIFO buffer.
+
   @param  TerminalDevice       Terminal driver private structure.
   @param  Key                  The key will be input.
 
@@ -1360,4 +1423,19 @@ TerminalConInTimerHandler (
   IN EFI_EVENT            Event,
   IN VOID                 *Context
   );
+
+
+/**
+  Process key notify.
+
+  @param  Event                 Indicates the event that invoke this function.
+  @param  Context               Indicates the calling context.
+**/
+VOID
+EFIAPI
+KeyNotifyProcessHandler (
+  IN  EFI_EVENT                 Event,
+  IN  VOID                      *Context
+  );
+
 #endif
diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c 
b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
index 5c3ea86fe104..799aabe3f0bc 100644
--- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
+++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
@@ -2,7 +2,7 @@
   Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
 
 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
 Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD 
License
@@ -94,6 +94,7 @@ TerminalConInReset (
   TerminalDevice->RawFiFo->Head     = TerminalDevice->RawFiFo->Tail;
   TerminalDevice->UnicodeFiFo->Head = TerminalDevice->UnicodeFiFo->Tail;
   TerminalDevice->EfiKeyFiFo->Head  = TerminalDevice->EfiKeyFiFo->Tail;
+  TerminalDevice->EfiKeyFiFoForNotify->Head = 
TerminalDevice->EfiKeyFiFoForNotify->Tail;
 
   if (EFI_ERROR (Status)) {
     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
@@ -599,6 +600,55 @@ TerminalConInTimerHandler (
 }
 
 /**
+  Process key notify.
+
+  @param  Event                 Indicates the event that invoke this function.
+  @param  Context               Indicates the calling context.
+**/
+VOID
+EFIAPI
+KeyNotifyProcessHandler (
+  IN  EFI_EVENT                 Event,
+  IN  VOID                      *Context
+  )
+{
+  TERMINAL_DEV                  *TerminalDevice;
+  EFI_INPUT_KEY                 Key;
+  EFI_KEY_DATA                  KeyData;
+  LIST_ENTRY                    *Link;
+  LIST_ENTRY                    *NotifyList;
+  TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
+  EFI_TPL                       OldTpl;
+
+  TerminalDevice = (TERMINAL_DEV *) Context;
+
+  //
+  // Invoke notification functions.
+  //
+  NotifyList = &TerminalDevice->NotifyList;
+  while (!IsEfiKeyFiFoForNotifyEmpty (TerminalDevice->EfiKeyFiFoForNotify)) {
+    //
+    // Enter critical section
+    //  
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+    EfiKeyFiFoForNotifyRemoveOneKey (TerminalDevice->EfiKeyFiFoForNotify, 
&Key);
+    CopyMem (&KeyData.Key, &Key, sizeof (EFI_INPUT_KEY));
+    KeyData.KeyState.KeyShiftState  = 0;
+    KeyData.KeyState.KeyToggleState = 0;
+    //
+    // Leave critical section
+    //
+    gBS->RestoreTPL (OldTpl);
+    for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = 
GetNextNode (NotifyList, Link)) {
+      CurrentNotify = CR (Link, TERMINAL_CONSOLE_IN_EX_NOTIFY, NotifyEntry, 
TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
+      if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
+        CurrentNotify->KeyNotificationFn (&KeyData);
+      }
+    }
+  }
+}
+
+/**
   Get one key out of serial buffer.
 
   @param  SerialIo           Serial I/O protocol attached to the serial device.
@@ -766,6 +816,126 @@ IsRawFiFoFull (
 /**
   Insert one pre-fetched key into the FIFO buffer.
 
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
+  @param  Input                 The key will be input.
+
+  @retval TRUE                  If insert successfully.
+  @retval FALSE                 If FIFO buffer is full before key insertion,
+                                and the key is lost.
+
+**/
+BOOLEAN
+EfiKeyFiFoForNotifyInsertOneKey (
+  EFI_KEY_FIFO                  *EfiKeyFiFo,
+  EFI_INPUT_KEY                 *Input
+  )
+{
+  UINT8                         Tail;
+
+  Tail = EfiKeyFiFo->Tail;
+
+  if (IsEfiKeyFiFoForNotifyFull (EfiKeyFiFo)) {
+    //
+    // FIFO is full
+    //
+    return FALSE;
+  }
+
+  CopyMem (&EfiKeyFiFo->Data[Tail], Input, sizeof (EFI_INPUT_KEY));
+
+  EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
+
+  return TRUE;
+}
+
+/**
+  Remove one pre-fetched key out of the FIFO buffer.
+
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
+  @param  Output                The key will be removed.
+
+  @retval TRUE                  If insert successfully.
+  @retval FALSE                 If FIFO buffer is empty before remove 
operation.
+
+**/
+BOOLEAN
+EfiKeyFiFoForNotifyRemoveOneKey (
+  EFI_KEY_FIFO                  *EfiKeyFiFo,
+  EFI_INPUT_KEY                 *Output
+  )
+{
+  UINT8                         Head;
+
+  Head = EfiKeyFiFo->Head;
+  ASSERT (Head < FIFO_MAX_NUMBER + 1);
+
+  if (IsEfiKeyFiFoForNotifyEmpty (EfiKeyFiFo)) {
+    //
+    // FIFO is empty
+    //
+    Output->ScanCode    = SCAN_NULL;
+    Output->UnicodeChar = 0;
+    return FALSE;
+  }
+
+  CopyMem (Output, &EfiKeyFiFo->Data[Head], sizeof (EFI_INPUT_KEY));
+
+  EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));
+
+  return TRUE;
+}
+
+/**
+  Clarify whether FIFO buffer is empty.
+
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
+
+  @retval TRUE                  If FIFO buffer is empty.
+  @retval FALSE                 If FIFO buffer is not empty.
+
+**/
+BOOLEAN
+IsEfiKeyFiFoForNotifyEmpty (
+  EFI_KEY_FIFO                  *EfiKeyFiFo
+  )
+{
+  if (EfiKeyFiFo->Head == EfiKeyFiFo->Tail) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Clarify whether FIFO buffer is full.
+
+  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
+
+  @retval TRUE                  If FIFO buffer is full.
+  @retval FALSE                 If FIFO buffer is not full.
+
+**/
+BOOLEAN
+IsEfiKeyFiFoForNotifyFull (
+  EFI_KEY_FIFO                  *EfiKeyFiFo
+  )
+{
+  UINT8                         Tail;
+  UINT8                         Head;
+
+  Tail = EfiKeyFiFo->Tail;
+  Head = EfiKeyFiFo->Head;
+
+  if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/**
+  Insert one pre-fetched key into the FIFO buffer.
+
   @param  TerminalDevice       Terminal driver private structure.
   @param  Key                  The key will be input.
 
@@ -793,7 +963,7 @@ EfiKeyFiFoInsertOneKey (
   KeyData.KeyState.KeyToggleState = 0;
 
   //
-  // Invoke notification functions if exist
+  // Signal KeyNotify process event if this key pressed matches any key 
registered.
   //
   NotifyList = &TerminalDevice->NotifyList;
   for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = 
GetNextNode (NotifyList,Link)) {
@@ -804,7 +974,8 @@ EfiKeyFiFoInsertOneKey (
                       TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
                       );
     if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
-      CurrentNotify->KeyNotificationFn (&KeyData);
+      EfiKeyFiFoForNotifyInsertOneKey (TerminalDevice->EfiKeyFiFoForNotify, 
Key);
+      gBS->SignalEvent (TerminalDevice->KeyNotifyProcessEvent);
     }
   }
   if (IsEfiKeyFiFoFull (TerminalDevice)) {
-- 
2.7.0.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to