Reviewed-by: Erik Bjorge <[email protected]>

> -----Original Message-----
> From: Daryl McDaniel [mailto:[email protected]]
> Sent: Sunday, January 3, 2016 2:45 PM
> To: [email protected]; Carsey, Jaben <[email protected]>; Bjorge, 
> Erik C
> <[email protected]>
> Subject: [PATCH] StdLib: Implement da_ConFlush() and flush I/O buffers when 
> closing a
> console device.
> 
> StdLib: Implement da_ConFlush() and flush I/O buffers when closing a console 
> device.
> 
> Add header file Efi/SysEfi.h
> 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 <[email protected]>
> 
> ---
> diff U3 a/StdLib/LibC/Uefi/Devices/Console/daConsole.c
> b/StdLib/LibC/Uefi/Devices/Console/daConsole.c
> --- a/StdLib/LibC/Uefi/Devices/Console/daConsole.c  Tue Nov 11 14:56:58 2014
> +++ b/StdLib/LibC/Uefi/Devices/Console/daConsole.c  Sun Jan 03 12:16:39 2016
> @@ -10,6 +10,7 @@
>    The devices status as a wide device is indicatd by _S_IWTTY being set in
>    f_iflags.
> 
> +  Copyright (c) 2016, Daryl McDaniel. All rights reserved.<BR>
>    Copyright (c) 2010 - 2014, 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 that accompanies this 
> distribution.
> @@ -37,6 +38,7 @@
>  #include  <sys/fcntl.h>
>  #include  <unistd.h>
>  #include  <sys/termios.h>
> +#include  <Efi/SysEfi.h>
>  #include  <kfile.h>
>  #include  <Device/Device.h>
>  #include  <Device/IIO.h>
> @@ -104,6 +106,65 @@
>    return i;
>  }
> 
> +/** Flush the console's IIO buffers.
> +
> +    Flush the IIO Input or Output buffers depending upon the mode
> +    of the specified file.
> +
> +    If the console is open for output, write any unwritten data in the output
> +    buffer to the console.
> +
> +    If the console is open for input or output, discard any remaining data
> +    in the associated buffers.
> +
> +    @param[in]    filp    Pointer to the target file's descriptor structure.
> +
> +    @retval     0     Always succeeds
> +**/
> +static
> +int
> +EFIAPI
> +da_ConFlush(
> +  struct __filedes *filp
> +)
> +{
> +  cIIO       *This;
> +  char       *MbcsPtr;
> +  ssize_t     NumProc;
> +  void       *OutPtr;
> +
> +  This = filp->devdata;
> +
> +  if (filp->f_iflags & S_ACC_READ)  {     // Readable so flush the input 
> buffer
> +    This->InBuf->Flush(This->InBuf, UNICODE_STRING_MAX);
> +  }
> +  if (filp->f_iflags & S_ACC_WRITE)  {    // Writable so flush the output 
> buffer
> +    // At this point, the characters to write are in OutBuf
> +    // First, linearize and consume the buffer
> +    NumProc = OutBuf->Read(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);
> +    if (NumProc > 0) {  // Optimization -- Nothing to do if no characters
> +      gMD->UString[NumProc] = 0;   // Ensure that the buffer is terminated
> +
> +      if(filp->f_iflags & _S_IWTTY) {
> +        // Output device expects wide characters, Output what we have
> +        OutPtr = gMD->UString;
> +      }
> +      else {
> +        // Output device expects narrow characters, convert to MBCS
> +        OutPtr = gMD->UString2;
> +        // Translate the wide buffer, gMD->UString into MBCS
> +        // in the buffer pointed to by OutPtr.
> +        // The returned value, NumProc, is the resulting number of bytes.
> +        NumProc = wcstombs((char *)OutPtr, (const wchar_t *)gMD->UString, 
> NumProc);
> +        ((char *)OutPtr)[NumProc] = 0;   // Ensure the buffer is terminated
> +      }
> +      // Do the actual write of the data
> +      (void) filp->f_ops->fo_write(filp, NULL, NumProc, OutPtr);
> +    }
> +  }
> +  return 0;
> +}
> +
>  /** Close an open file.
> 
>      @param[in]  filp    Pointer to the file descriptor structure for this 
> file.
> @@ -127,6 +188,13 @@
>      EFIerrno = RETURN_INVALID_PARAMETER;
>      return -1;    // Looks like a bad File Descriptor pointer
>    }
> +  // Stream and filp look OK, so continue.
> +  // Flush the I/O buffers
> +  (void) da_ConFlush(filp);
> +
> +  // Break the connection to IIO
> +  filp->devdata = NULL;
> +
>    gMD->StdIo[Stream->InstanceNum] = NULL;   // Mark the stream as closed
>    return 0;
>  }
> @@ -188,10 +256,10 @@
>          by da_ConWrite are WIDE characters.  It is the responsibility of the
>          higher-level function(s) to perform any necessary conversions.
> 
> -    @param[in,out]  BufferSize  Number of characters in Buffer.
> +  @param[in,out]  BufferSize  Number of characters in Buffer.
>    @param[in]      Buffer      The WCS string to be displayed
> 
> -    @return   The number of Characters written.
> +  @return   The number of Characters written.
>  */
>  static
>  ssize_t
> @@ -525,7 +593,7 @@
>    wchar_t            *MPath           // Not used for console devices
>    )
>  {
> -  ConInstance                      *Stream;
> +  ConInstance    *Stream;
>    UINT32          Instance;
>    int             RetVal = -1;
> 
> @@ -646,68 +714,68 @@
>      IIO = New_cIIO();
>      if(IIO == NULL) {
>        FreePool(ConInstanceList);
> -  }
> +    }
>      else {
>        Status = RETURN_SUCCESS;
> -  for( i = 0; i < NUM_SPECIAL; ++i) {
> -    // Get pointer to instance.
> -    Stream = &ConInstanceList[i];
> -
> -    Stream->Cookie      = CON_COOKIE;
> -    Stream->InstanceNum = i;
> -    Stream->CharState.A = 0;    // Start in the initial state
> -
> -    switch(i) {
> -      case STDIN_FILENO:
> -        Stream->Dev = SystemTable->ConIn;
> -        break;
> -      case STDOUT_FILENO:
> -        Stream->Dev = SystemTable->ConOut;
> -        break;
> -      case STDERR_FILENO:
> -        if(SystemTable->StdErr == NULL) {
> -          Stream->Dev = SystemTable->ConOut;
> -        }
> -        else {
> -          Stream->Dev = SystemTable->StdErr;
> +      for( i = 0; i < NUM_SPECIAL; ++i) {
> +        // Get pointer to instance.
> +        Stream = &ConInstanceList[i];
> +
> +        Stream->Cookie      = CON_COOKIE;
> +        Stream->InstanceNum = i;
> +        Stream->CharState.A = 0;    // Start in the initial state
> +
> +        switch(i) {
> +          case STDIN_FILENO:
> +            Stream->Dev = SystemTable->ConIn;
> +            break;
> +          case STDOUT_FILENO:
> +            Stream->Dev = SystemTable->ConOut;
> +            break;
> +          case STDERR_FILENO:
> +            if(SystemTable->StdErr == NULL) {
> +              Stream->Dev = SystemTable->ConOut;
> +            }
> +            else {
> +              Stream->Dev = SystemTable->StdErr;
> +            }
> +            break;
> +          default:
> +            return RETURN_VOLUME_CORRUPTED;     // This is a "should never 
> happen" case.
>          }
> -        break;
> -      default:
> -        return RETURN_VOLUME_CORRUPTED;     // This is a "should never 
> happen" case.
> -    }
> -
> -    Stream->Abstraction.fo_close    = &da_ConClose;
> -    Stream->Abstraction.fo_read     = &da_ConRead;
> -    Stream->Abstraction.fo_write    = &da_ConWrite;
> -    Stream->Abstraction.fo_stat     = &da_ConStat;
> -    Stream->Abstraction.fo_lseek    = &da_ConSeek;
> -    Stream->Abstraction.fo_fcntl    = &fnullop_fcntl;
> -    Stream->Abstraction.fo_ioctl    = &da_ConIoctl;
> -    Stream->Abstraction.fo_poll     = &da_ConPoll;
> -    Stream->Abstraction.fo_flush    = &fnullop_flush;
> -    Stream->Abstraction.fo_delete   = &fbadop_delete;
> -    Stream->Abstraction.fo_mkdir    = &fbadop_mkdir;
> -    Stream->Abstraction.fo_rmdir    = &fbadop_rmdir;
> -    Stream->Abstraction.fo_rename   = &fbadop_rename;
> 
> -    Stream->NumRead     = 0;
> -    Stream->NumWritten  = 0;
> -    Stream->UnGetKey    = CHAR_NULL;
> +        Stream->Abstraction.fo_close    = &da_ConClose;
> +        Stream->Abstraction.fo_read     = &da_ConRead;
> +        Stream->Abstraction.fo_write    = &da_ConWrite;
> +        Stream->Abstraction.fo_stat     = &da_ConStat;
> +        Stream->Abstraction.fo_lseek    = &da_ConSeek;
> +        Stream->Abstraction.fo_fcntl    = &fnullop_fcntl;
> +        Stream->Abstraction.fo_ioctl    = &da_ConIoctl;
> +        Stream->Abstraction.fo_poll     = &da_ConPoll;
> +        Stream->Abstraction.fo_flush    = &da_ConFlush;
> +        Stream->Abstraction.fo_delete   = &fbadop_delete;
> +        Stream->Abstraction.fo_mkdir    = &fbadop_mkdir;
> +        Stream->Abstraction.fo_rmdir    = &fbadop_rmdir;
> +        Stream->Abstraction.fo_rename   = &fbadop_rename;
> +
> +        Stream->NumRead     = 0;
> +        Stream->NumWritten  = 0;
> +        Stream->UnGetKey    = CHAR_NULL;
> 
> -    if(Stream->Dev == NULL) {
> -      continue;                 // No device for this stream.
> -    }
> -        ConNode[i] = __DevRegister(stdioNames[i], NULL, &da_ConOpen, Stream,
> -                                   1, sizeof(ConInstance), stdioFlags[i]);
> -    if(ConNode[i] == NULL) {
> -          Status = EFIerrno;    // Grab error code that DevRegister produced.
> -      break;
> -    }
> -    Stream->Parent = ConNode[i];
> -  }
> -  /* Initialize Ioctl flags until Ioctl is really implemented. */
> -  TtyCooked = TRUE;
> -  TtyEcho   = TRUE;
> +        if(Stream->Dev == NULL) {
> +          continue;                 // No device for this stream.
> +        }
> +            ConNode[i] = __DevRegister(stdioNames[i], NULL, &da_ConOpen, 
> Stream,
> +                                       1, sizeof(ConInstance), 
> stdioFlags[i]);
> +        if(ConNode[i] == NULL) {
> +              Status = EFIerrno;    // Grab error code that DevRegister 
> produced.
> +          break;
> +        }
> +        Stream->Parent = ConNode[i];
> +      }
> +      /* Initialize Ioctl flags until Ioctl is really implemented. */
> +      TtyCooked = TRUE;
> +      TtyEcho   = TRUE;
>      }
>    }
>    return  Status;
> @@ -751,15 +819,5 @@
>    void *
>    )
>  {
> -}
> -
> -static
> -int
> -EFIAPI
> -da_ConFlush(
> -  struct __filedes *filp
> -  )
> -{
> -  return 0;
>  }
>  #endif  /* Not implemented for Console */
> --
> Daryl McDaniel
> 

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to