From 4e8f2b290e92891b4248cc680d6751b73331d545 Mon Sep 17 00:00:00 2001 From: Daryl McDaniel Date: Wed, 6 Jan 2016 00:05:02 +0000 Subject: StdLib: Implement da_ConFlush() and flush I/O buffers when closing a console device. 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 Reviewed-by: Erik Bjorge 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 | 200 +++++++++++++++++---------- 1 file changed, 129 insertions(+), 71 deletions(-) (limited to 'StdLib') diff --git a/StdLib/LibC/Uefi/Devices/Console/daConsole.c b/StdLib/LibC/Uefi/Devices/Console/daConsole.c index d926a0c56e..f7ad852cc7 100644 --- a/StdLib/LibC/Uefi/Devices/Console/daConsole.c +++ b/StdLib/LibC/Uefi/Devices/Console/daConsole.c @@ -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.
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.
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 #include #include +#include #include #include #include @@ -104,6 +106,65 @@ WideTtyCvt( CHAR16 *dest, const char *buf, ssize_t n, mbstate_t *Cs) 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 @@ da_ConClose( 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 @@ da_ConSeek( 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 @@ da_ConOpen( wchar_t *MPath // Not used for console devices ) { - ConInstance *Stream; + ConInstance *Stream; UINT32 Instance; int RetVal = -1; @@ -646,68 +714,68 @@ __Cons_construct( 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; + 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. } - else { - Stream->Dev = SystemTable->StdErr; - } - 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; - 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; + 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; } } return Status; @@ -752,14 +820,4 @@ da_ConCntl( ) { } - -static -int -EFIAPI -da_ConFlush( - struct __filedes *filp - ) -{ - return 0; -} #endif /* Not implemented for Console */ -- cgit v1.2.3