]> git.proxmox.com Git - mirror_edk2.git/commitdiff
StdLib: Implement da_ConFlush() and flush I/O buffers when closing a console device.
authorDaryl McDaniel <edk2-lists@mc2research.org>
Wed, 6 Jan 2016 00:05:02 +0000 (00:05 +0000)
committerdarylm503 <darylm503@Edk2>
Wed, 6 Jan 2016 00:05:02 +0000 (00:05 +0000)
Add header file Efi/SysEfi.h
Clean up some indent issues.
Implement function da_ConFlush()
Modify da_ConClose() to flush its buffers and clean up better upon close.
Construct the console instance using the new da_ConFlush() instead of the nullop function.
Remove da_ConFlush() from the "Not implemented (yet?)" place holder.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Daryl McDaniel <edk2-lists@mc2research.org>
Reviewed-by: Erik Bjorge <erik.c.bjorge@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19587 6f19259b-4bc3-4df7-8a09-765794883524

StdLib/LibC/Uefi/Devices/Console/daConsole.c

index d926a0c56e5e205b7efe80782d89fcaa3a672a4a..f7ad852cc7e80a0672f15c31978d97933ae80c50 100644 (file)
@@ -10,6 +10,7 @@
   The devices status as a wide device is indicatd by _S_IWTTY being set in\r
   f_iflags.\r
 \r
+  Copyright (c) 2016, Daryl McDaniel. All rights reserved.<BR>\r
   Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials are licensed and made available under\r
   the terms and conditions of the BSD License that accompanies this distribution.\r
@@ -37,6 +38,7 @@
 #include  <sys/fcntl.h>\r
 #include  <unistd.h>\r
 #include  <sys/termios.h>\r
+#include  <Efi/SysEfi.h>\r
 #include  <kfile.h>\r
 #include  <Device/Device.h>\r
 #include  <Device/IIO.h>\r
@@ -104,6 +106,65 @@ WideTtyCvt( CHAR16 *dest, const char *buf, ssize_t n, mbstate_t *Cs)
   return i;\r
 }\r
 \r
+/** Flush the console's IIO buffers.\r
+\r
+    Flush the IIO Input or Output buffers depending upon the mode\r
+    of the specified file.\r
+\r
+    If the console is open for output, write any unwritten data in the output\r
+    buffer to the console.\r
+\r
+    If the console is open for input or output, discard any remaining data\r
+    in the associated buffers.\r
+\r
+    @param[in]    filp    Pointer to the target file's descriptor structure.\r
+\r
+    @retval     0     Always succeeds\r
+**/\r
+static\r
+int\r
+EFIAPI\r
+da_ConFlush(\r
+  struct __filedes *filp\r
+)\r
+{\r
+  cIIO       *This;\r
+  char       *MbcsPtr;\r
+  ssize_t     NumProc;\r
+  void       *OutPtr;\r
+\r
+  This = filp->devdata;\r
+\r
+  if (filp->f_iflags & S_ACC_READ)  {     // Readable so flush the input buffer\r
+    This->InBuf->Flush(This->InBuf, UNICODE_STRING_MAX);\r
+  }\r
+  if (filp->f_iflags & S_ACC_WRITE)  {    // Writable so flush the output buffer\r
+    // At this point, the characters to write are in OutBuf\r
+    // First, linearize and consume the buffer\r
+    NumProc = OutBuf->Read(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);\r
+    if (NumProc > 0) {  // Optimization -- Nothing to do if no characters\r
+      gMD->UString[NumProc] = 0;   // Ensure that the buffer is terminated\r
+\r
+      if(filp->f_iflags & _S_IWTTY) {\r
+        // Output device expects wide characters, Output what we have\r
+        OutPtr = gMD->UString;\r
+      }\r
+      else {\r
+        // Output device expects narrow characters, convert to MBCS\r
+        OutPtr = gMD->UString2;\r
+        // Translate the wide buffer, gMD->UString into MBCS\r
+        // in the buffer pointed to by OutPtr.\r
+        // The returned value, NumProc, is the resulting number of bytes.\r
+        NumProc = wcstombs((char *)OutPtr, (const wchar_t *)gMD->UString, NumProc);\r
+        ((char *)OutPtr)[NumProc] = 0;   // Ensure the buffer is terminated\r
+      }\r
+      // Do the actual write of the data\r
+      (void) filp->f_ops->fo_write(filp, NULL, NumProc, OutPtr);\r
+    }\r
+  }\r
+  return 0;\r
+}\r
+\r
 /** Close an open file.\r
 \r
     @param[in]  filp    Pointer to the file descriptor structure for this file.\r
@@ -127,6 +188,13 @@ da_ConClose(
     EFIerrno = RETURN_INVALID_PARAMETER;\r
     return -1;    // Looks like a bad File Descriptor pointer\r
   }\r
+  // Stream and filp look OK, so continue.\r
+  // Flush the I/O buffers\r
+  (void) da_ConFlush(filp);\r
+\r
+  // Break the connection to IIO\r
+  filp->devdata = NULL;\r
+\r
   gMD->StdIo[Stream->InstanceNum] = NULL;   // Mark the stream as closed\r
   return 0;\r
 }\r
@@ -188,10 +256,10 @@ da_ConSeek(
         by da_ConWrite are WIDE characters.  It is the responsibility of the\r
         higher-level function(s) to perform any necessary conversions.\r
 \r
-    @param[in,out]  BufferSize  Number of characters in Buffer.\r
+  @param[in,out]  BufferSize  Number of characters in Buffer.\r
   @param[in]      Buffer      The WCS string to be displayed\r
 \r
-    @return   The number of Characters written.\r
+  @return   The number of Characters written.\r
 */\r
 static\r
 ssize_t\r
@@ -525,7 +593,7 @@ da_ConOpen(
   wchar_t            *MPath           // Not used for console devices\r
   )\r
 {\r
-  ConInstance                      *Stream;\r
+  ConInstance    *Stream;\r
   UINT32          Instance;\r
   int             RetVal = -1;\r
 \r
@@ -646,68 +714,68 @@ __Cons_construct(
     IIO = New_cIIO();\r
     if(IIO == NULL) {\r
       FreePool(ConInstanceList);\r
-  }\r
+    }\r
     else {\r
       Status = RETURN_SUCCESS;\r
-  for( i = 0; i < NUM_SPECIAL; ++i) {\r
-    // Get pointer to instance.\r
-    Stream = &ConInstanceList[i];\r
-\r
-    Stream->Cookie      = CON_COOKIE;\r
-    Stream->InstanceNum = i;\r
-    Stream->CharState.A = 0;    // Start in the initial state\r
-\r
-    switch(i) {\r
-      case STDIN_FILENO:\r
-        Stream->Dev = SystemTable->ConIn;\r
-        break;\r
-      case STDOUT_FILENO:\r
-        Stream->Dev = SystemTable->ConOut;\r
-        break;\r
-      case STDERR_FILENO:\r
-        if(SystemTable->StdErr == NULL) {\r
-          Stream->Dev = SystemTable->ConOut;\r
+      for( i = 0; i < NUM_SPECIAL; ++i) {\r
+        // Get pointer to instance.\r
+        Stream = &ConInstanceList[i];\r
+\r
+        Stream->Cookie      = CON_COOKIE;\r
+        Stream->InstanceNum = i;\r
+        Stream->CharState.A = 0;    // Start in the initial state\r
+\r
+        switch(i) {\r
+          case STDIN_FILENO:\r
+            Stream->Dev = SystemTable->ConIn;\r
+            break;\r
+          case STDOUT_FILENO:\r
+            Stream->Dev = SystemTable->ConOut;\r
+            break;\r
+          case STDERR_FILENO:\r
+            if(SystemTable->StdErr == NULL) {\r
+              Stream->Dev = SystemTable->ConOut;\r
+            }\r
+            else {\r
+              Stream->Dev = SystemTable->StdErr;\r
+            }\r
+            break;\r
+          default:\r
+            return RETURN_VOLUME_CORRUPTED;     // This is a "should never happen" case.\r
         }\r
-        else {\r
-          Stream->Dev = SystemTable->StdErr;\r
-        }\r
-        break;\r
-      default:\r
-        return RETURN_VOLUME_CORRUPTED;     // This is a "should never happen" case.\r
-    }\r
-\r
-    Stream->Abstraction.fo_close    = &da_ConClose;\r
-    Stream->Abstraction.fo_read     = &da_ConRead;\r
-    Stream->Abstraction.fo_write    = &da_ConWrite;\r
-    Stream->Abstraction.fo_stat     = &da_ConStat;\r
-    Stream->Abstraction.fo_lseek    = &da_ConSeek;\r
-    Stream->Abstraction.fo_fcntl    = &fnullop_fcntl;\r
-    Stream->Abstraction.fo_ioctl    = &da_ConIoctl;\r
-    Stream->Abstraction.fo_poll     = &da_ConPoll;\r
-    Stream->Abstraction.fo_flush    = &fnullop_flush;\r
-    Stream->Abstraction.fo_delete   = &fbadop_delete;\r
-    Stream->Abstraction.fo_mkdir    = &fbadop_mkdir;\r
-    Stream->Abstraction.fo_rmdir    = &fbadop_rmdir;\r
-    Stream->Abstraction.fo_rename   = &fbadop_rename;\r
-\r
-    Stream->NumRead     = 0;\r
-    Stream->NumWritten  = 0;\r
-    Stream->UnGetKey    = CHAR_NULL;\r
 \r
-    if(Stream->Dev == NULL) {\r
-      continue;                 // No device for this stream.\r
-    }\r
-        ConNode[i] = __DevRegister(stdioNames[i], NULL, &da_ConOpen, Stream,\r
-                                   1, sizeof(ConInstance), stdioFlags[i]);\r
-    if(ConNode[i] == NULL) {\r
-          Status = EFIerrno;    // Grab error code that DevRegister produced.\r
-      break;\r
-    }\r
-    Stream->Parent = ConNode[i];\r
-  }\r
-  /* Initialize Ioctl flags until Ioctl is really implemented. */\r
-  TtyCooked = TRUE;\r
-  TtyEcho   = TRUE;\r
+        Stream->Abstraction.fo_close    = &da_ConClose;\r
+        Stream->Abstraction.fo_read     = &da_ConRead;\r
+        Stream->Abstraction.fo_write    = &da_ConWrite;\r
+        Stream->Abstraction.fo_stat     = &da_ConStat;\r
+        Stream->Abstraction.fo_lseek    = &da_ConSeek;\r
+        Stream->Abstraction.fo_fcntl    = &fnullop_fcntl;\r
+        Stream->Abstraction.fo_ioctl    = &da_ConIoctl;\r
+        Stream->Abstraction.fo_poll     = &da_ConPoll;\r
+        Stream->Abstraction.fo_flush    = &da_ConFlush;\r
+        Stream->Abstraction.fo_delete   = &fbadop_delete;\r
+        Stream->Abstraction.fo_mkdir    = &fbadop_mkdir;\r
+        Stream->Abstraction.fo_rmdir    = &fbadop_rmdir;\r
+        Stream->Abstraction.fo_rename   = &fbadop_rename;\r
+\r
+        Stream->NumRead     = 0;\r
+        Stream->NumWritten  = 0;\r
+        Stream->UnGetKey    = CHAR_NULL;\r
+\r
+        if(Stream->Dev == NULL) {\r
+          continue;                 // No device for this stream.\r
+        }\r
+            ConNode[i] = __DevRegister(stdioNames[i], NULL, &da_ConOpen, Stream,\r
+                                       1, sizeof(ConInstance), stdioFlags[i]);\r
+        if(ConNode[i] == NULL) {\r
+              Status = EFIerrno;    // Grab error code that DevRegister produced.\r
+          break;\r
+        }\r
+        Stream->Parent = ConNode[i];\r
+      }\r
+      /* Initialize Ioctl flags until Ioctl is really implemented. */\r
+      TtyCooked = TRUE;\r
+      TtyEcho   = TRUE;\r
     }\r
   }\r
   return  Status;\r
@@ -752,14 +820,4 @@ da_ConCntl(
   )\r
 {\r
 }\r
-\r
-static\r
-int\r
-EFIAPI\r
-da_ConFlush(\r
-  struct __filedes *filp\r
-  )\r
-{\r
-  return 0;\r
-}\r
 #endif  /* Not implemented for Console */\r