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
#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
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
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
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
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
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
)\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