summaryrefslogtreecommitdiff
path: root/StdLib/LibC/Uefi/InteractiveIO
diff options
context:
space:
mode:
Diffstat (limited to 'StdLib/LibC/Uefi/InteractiveIO')
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/CanonRead.c161
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/IIO.c373
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/IIO.inf51
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/IIOecho.c141
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h33
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c288
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h129
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c210
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c89
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c285
10 files changed, 1760 insertions, 0 deletions
diff --git a/StdLib/LibC/Uefi/InteractiveIO/CanonRead.c b/StdLib/LibC/Uefi/InteractiveIO/CanonRead.c
new file mode 100644
index 0000000000..db6af6e4bf
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/CanonRead.c
@@ -0,0 +1,161 @@
+/** @file
+ Canonical Interactive Input Function.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+
+ Copyright (c) 2012, 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
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <Uefi.h>
+
+#include <LibConfig.h>
+
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <MainData.h>
+#include "IIOutilities.h"
+#include "IIOechoCtrl.h"
+
+/** Read a line from the input file in canonical mode.
+ Perform echoing and input processing as directed by the termios flags.
+
+ @param[in] filp A pointer to a file descriptor structure.
+
+ @return The number of characters in the input buffer, or -1 if there
+ was an error.
+**/
+ssize_t
+IIO_CanonRead (
+ struct __filedes *filp
+ )
+{
+ cIIO *This;
+ cFIFO *InBuf;
+ struct termios *Termio;
+ struct __filedes *fpOut;
+ size_t NumRead;
+ wint_t InChar;
+ tcflag_t IFlag;
+ tcflag_t LFlag;
+ BOOLEAN EchoIsOK;
+ BOOLEAN Activate;
+ BOOLEAN FirstRead;
+ int OutMode;
+ UINTN MaxColumn;
+ UINTN MaxRow;
+
+ NumRead = MAX_INPUT; // Workaround "potentially uninitialized" warning
+ EchoIsOK = FALSE;
+ FirstRead = TRUE;
+ This = filp->devdata;
+ Termio = &This->Termio;
+ InBuf = This->InBuf;
+
+ // Get a copy of the flags we are going to use
+ IFlag = Termio->c_iflag;
+ LFlag = Termio->c_lflag;
+
+ /* Determine what the current screen size is. Also validates the output device. */
+ OutMode = IIO_GetOutputSize(STDOUT_FILENO, &MaxColumn, &MaxRow);
+ if(OutMode >= 0) {
+ /* Set the maximum screen dimensions. */
+ This->MaxColumn = MaxColumn;
+ This->MaxRow = MaxRow;
+
+ /* Record where the cursor is at the beginning of this Input operation.
+ The currently set stdout device is used to determine this. If there is
+ no stdout, or stdout is not an interactive device, nothing is recorded.
+ */
+ if (IIO_GetCursorPosition(STDOUT_FILENO, &This->InitialXY.Column, &This->InitialXY.Row) >= 0) {
+ This->CurrentXY.Column = This->InitialXY.Column;
+ This->CurrentXY.Row = This->InitialXY.Row;
+ EchoIsOK = TRUE; // Can only echo to stdout
+ }
+ }
+
+ // For now, we only echo to stdout.
+ fpOut = &gMD->fdarray[STDOUT_FILENO];
+
+ // Input and process characters until BufferSize is exhausted.
+ do {
+ InChar = IIO_GetInChar(filp, FirstRead);
+ FirstRead = FALSE;
+ Activate = TRUE;
+ if(InChar == CHAR_CARRIAGE_RETURN) {
+ if((IFlag & IGNCR) != 0) {
+ continue; // Restart the do loop, discarding the CR
+ }
+ else if((IFlag & ICRNL) != 0) {
+ InChar = L'\n';
+ }
+ }
+ else if(InChar == CHAR_LINEFEED) {
+ if((IFlag & INLCR) != 0) {
+ InChar = L'\r';
+ }
+ }
+ else if(CCEQ(Termio->c_cc[VINTR], InChar)) {
+ if((LFlag & ISIG) != 0) {
+ // Raise Signal
+ // Flush Input Buffer
+ // Return to caller
+ InChar = IIO_ECHO_DISCARD;
+ errno = EINTR;
+ }
+ else {
+ Activate = FALSE;
+ }
+ }
+ else if(CCEQ(Termio->c_cc[VQUIT], InChar)) {
+ if((LFlag & ISIG) != 0) {
+ // Raise Signal
+ // Flush Input Buffer
+ // Return to caller
+ InChar = IIO_ECHO_DISCARD;
+ errno = EINTR;
+ }
+ else {
+ Activate = FALSE;
+ }
+ }
+ else if(CCEQ(Termio->c_cc[VEOF], InChar)) {
+ InChar = WEOF;
+ }
+ else if(CCEQ(Termio->c_cc[VEOL], InChar)) {
+ EchoIsOK = FALSE; // Buffer, but don't echo this character
+ }
+ else if(CCEQ(Termio->c_cc[VERASE], InChar)) {
+ InChar = IIO_ECHO_ERASE;
+ Activate = FALSE;
+ }
+ else if(CCEQ(Termio->c_cc[VKILL], InChar)) {
+ InChar = IIO_ECHO_KILL;
+ Activate = FALSE;
+ }
+ else {
+ if((InChar < TtySpecKeyMin) || (InChar >= TtyFunKeyMax)) {
+ Activate = FALSE;
+ }
+ }
+ /** The Echo function is responsible for:
+ * Adding the character to the input buffer, if appropriate.
+ * Removing characters from the input buffer for ERASE and KILL processing.
+ * Visually removing characters from the screen if ECHOE is set.
+ * Ensuring one can not backspace beyond the beginning of the input text.
+ * Sending final echo strings to output.
+ **/
+ (void)This->Echo(fpOut, (wchar_t)InChar, EchoIsOK);
+ NumRead = InBuf->Count(InBuf, AsElements);
+ } while((NumRead < MAX_INPUT) &&
+ (Activate == FALSE));
+
+ return (ssize_t)NumRead;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIO.c b/StdLib/LibC/Uefi/InteractiveIO/IIO.c
new file mode 100644
index 0000000000..65b61d9bcc
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/IIO.c
@@ -0,0 +1,373 @@
+/** @file
+ Definitions for the Interactive IO library.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+
+ Copyright (c) 2012, 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
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <Uefi.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <LibConfig.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <MainData.h>
+#include "IIOutilities.h"
+#include "IIOechoCtrl.h"
+
+/** Read from an Interactive IO device.
+
+ NOTE: If _S_IWTTY is set, the internal buffer contains WIDE characters.
+ They will need to be converted to MBCS when returned.
+
+ Input is line buffered if ICANON is set,
+ otherwise MIN determines how many characters to input.
+ Currently MIN is always zero, meaning 0 or 1 character is input in
+ noncanonical mode.
+
+ @param[in] filp Pointer to the descriptor of the device (file) to be read.
+ @param[in] BufferSize Maximum number of bytes to be returned to the caller.
+ @param[out] Buffer Pointer to the buffer where the input is to be stored.
+
+ @retval -1 An error occurred. No data is available.
+ @retval 0 No data was available. Try again later.
+ @retval >0 The number of bytes consumed by the returned data.
+**/
+static
+ssize_t
+EFIAPI
+IIO_Read(
+ struct __filedes *filp,
+ size_t BufferSize,
+ VOID *Buffer
+ )
+{
+ cIIO *This;
+ ssize_t NumRead;
+ tcflag_t Flags;
+ size_t XlateSz;
+ size_t Needed;
+
+ NumRead = -1;
+ This = filp->devdata;
+ if(This != NULL) {
+ Flags = This->Termio.c_lflag;
+ if(Flags & ICANON) {
+ NumRead = IIO_CanonRead(filp);
+ }
+ else {
+ NumRead = IIO_NonCanonRead(filp);
+ }
+ // At this point, the input has been accumulated in the input buffer.
+ if(filp->f_iflags & _S_IWTTY) {
+ // Data in InBuf is wide characters. Convert to MBCS
+ // First, convert into a linear buffer
+ NumRead = This->InBuf->Copy(This->InBuf, gMD->UString2, (INT32)UNICODE_STRING_MAX-1);
+ gMD->UString2[NumRead] = 0; // Ensure that the buffer is terminated
+ // Determine the needed space
+ XlateSz = EstimateWtoM((const wchar_t *)gMD->UString2, BufferSize, &Needed);
+
+ // Now translate this into MBCS in Buffer
+ NumRead = wcstombs((char *)Buffer, (const wchar_t *)gMD->UString2, XlateSz);
+
+ // Consume the translated characters
+ (void)This->InBuf->Flush(This->InBuf, Needed);
+ }
+ else {
+ // Data in InBuf is narrow characters. Use verbatim.
+ NumRead = This->InBuf->Read(This->InBuf, Buffer, (INT32)BufferSize);
+ }
+ }
+ return NumRead;
+}
+
+/** Process characters from buffer buf and write them to the output device
+ specified by filp.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[in] buf Pointer to the MBCS string to be output.
+ @param[in] N Number of bytes in buf.
+
+ @retval >=0 Number of bytes sent to the output device.
+**/
+static
+ssize_t
+EFIAPI
+IIO_Write(
+ struct __filedes *filp,
+ const char *buf,
+ ssize_t N
+ )
+{
+ cIIO *This;
+ cFIFO *OutBuf;
+ mbstate_t *OutState;
+ char *MbcsPtr;
+ ssize_t NumWritten;
+ ssize_t NumProc;
+ size_t CharLen;
+ UINTN MaxColumn;
+ UINTN MaxRow;
+ wchar_t OutChar[2]; // Just in case we run into 4-byte MBCS character
+ int OutMode;
+
+ errno = 0; // indicate no error as default
+ NumWritten = -1;
+
+ /* Determine what the current screen size is. Also validates the output device. */
+ OutMode = IIO_GetOutputSize(filp->MyFD, &MaxColumn, &MaxRow);
+
+ This = filp->devdata;
+ if((This != NULL) && (OutMode >= 0)) {
+ if(filp->MyFD == STDERR_FILENO) {
+ OutBuf = This->ErrBuf;
+ OutState = &This->ErrState;
+ }
+ else {
+ OutBuf = This->OutBuf;
+ OutState = &This->OutState;
+ }
+
+ /* Set the maximum screen dimensions. */
+ This->MaxColumn = MaxColumn;
+ This->MaxRow = MaxRow;
+
+ /* Record where the cursor is at the beginning of the Output operation. */
+ (void)IIO_GetCursorPosition(filp->MyFD, &This->InitialXY.Column, &This->InitialXY.Row);
+ This->CurrentXY.Column = This->InitialXY.Column;
+ This->CurrentXY.Row = This->InitialXY.Row;
+
+
+ NumWritten = 0;
+ OutChar[0] = (wchar_t)buf[0];
+ while((OutChar[0] != 0) && (NumWritten < N)) {
+ CharLen = mbrtowc(OutChar, (const char *)&buf[NumWritten], MB_CUR_MAX, OutState);
+ NumProc = IIO_WriteOne(filp, OutBuf, OutChar[0]);
+ if(NumProc > 0) {
+ // Successfully processed and buffered one character
+ NumWritten += CharLen; // Index of start of next character
+ }
+ else if(NumProc == -1) {
+ // Encoding Error
+ (void)mbrtowc(NULL, NULL, 1, OutState); // Re-Initialize the conversion state
+ errno = EILSEQ;
+ break;
+ }
+ else {
+ // Last character was incomplete
+ break;
+ }
+ }
+ // At this point, the characters to write are in OutBuf
+ // First, linearize the buffer
+ NumWritten = OutBuf->Copy(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);
+ gMD->UString[NumWritten] = 0; // Ensure that the buffer is terminated
+
+ if(filp->f_iflags & _S_IWTTY) {
+ // Output device expects wide characters, Output what we have
+ NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, gMD->UString);
+ }
+ else {
+ // Output device expects narrow characters, convert to MBCS
+ MbcsPtr = (char *)gMD->UString2;
+ // Determine the needed space
+ NumProc = (ssize_t)EstimateWtoM((const wchar_t *)gMD->UString, UNICODE_STRING_MAX * sizeof(wchar_t), &CharLen);
+
+ // Now translate this into MBCS in Buffer
+ NumWritten = wcstombs(MbcsPtr, (const wchar_t *)gMD->UString, NumProc);
+ MbcsPtr[NumWritten] = 0; // Ensure the buffer is terminated
+
+ // Send the MBCS buffer to Output
+ NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, MbcsPtr);
+ }
+ // Consume the translated characters
+ (void)OutBuf->Flush(OutBuf, NumWritten);
+ }
+ else {
+ if(This == NULL) {
+ errno = EINVAL;
+ }
+ // Otherwise, errno is already set.
+ }
+ return NumWritten;
+}
+
+/** Echo a character to an output device.
+ Performs translation and edit processing depending upon termios flags.
+
+ @param[in] filp A pointer to a file descriptor structure.
+ @param[in] EChar The character to echo.
+ @param[in] EchoIsOK TRUE if the caller has determined that characters
+ should be echoed. Otherwise, just buffer.
+
+ @return Returns the number of characters actually output.
+**/
+static
+ssize_t
+EFIAPI
+IIO_Echo(
+ struct __filedes *filp,
+ wchar_t EChar,
+ BOOLEAN EchoIsOK
+ )
+{
+ cIIO *This;
+ ssize_t NumWritten;
+ cFIFO *OutBuf;
+ char *MbcsPtr;
+ ssize_t NumProc;
+ tcflag_t LFlags;
+
+ NumWritten = -1;
+ This = filp->devdata;
+ if(This != NULL) {
+ OutBuf = This->OutBuf;
+ LFlags = This->Termio.c_lflag & (ECHOK | ECHOE);
+
+ if((EChar >= TtyFunKeyMin) && (EChar < TtyFunKeyMax)) {
+ // A special function key was pressed, buffer it, don't echo, and activate.
+ // Process and buffer the character. May produce multiple characters.
+ NumProc = IIO_EchoOne(filp, EChar, FALSE); // Don't echo this character
+ EChar = CHAR_LINEFEED; // Every line must end with '\n' (legacy)
+ }
+ // Process and buffer the character. May produce multiple characters.
+ NumProc = IIO_EchoOne(filp, EChar, EchoIsOK);
+
+ // At this point, the character(s) to write are in OutBuf
+ // First, linearize the buffer
+ NumWritten = OutBuf->Copy(OutBuf, gMD->UString, UNICODE_STRING_MAX-1);
+ gMD->UString[NumWritten] = 0; // Ensure that the buffer is terminated
+
+ if((EChar == IIO_ECHO_KILL) && (LFlags & ECHOE) && EchoIsOK) {
+ // Position the cursor to the start of input.
+ (void)IIO_SetCursorPosition(filp, &This->InitialXY);
+ }
+ // Output the buffer
+ if(filp->f_iflags & _S_IWTTY) {
+ // Output device expects wide characters, Output what we have
+ NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, gMD->UString);
+ }
+ else {
+ // Output device expects narrow characters, convert to MBCS
+ MbcsPtr = (char *)gMD->UString2;
+ // Determine the needed space
+ NumProc = (ssize_t)EstimateWtoM((const wchar_t *)gMD->UString, UNICODE_STRING_MAX * sizeof(wchar_t), NULL);
+
+ // Now translate this into MBCS in Buffer
+ NumWritten = wcstombs(MbcsPtr, (const wchar_t *)gMD->UString, NumProc);
+ MbcsPtr[NumWritten] = 0; // Ensure the buffer is terminated
+
+ // Send the MBCS buffer to Output
+ NumWritten = filp->f_ops->fo_write(filp, NULL, NumWritten, MbcsPtr);
+ }
+ // Consume the echoed characters
+ (void)OutBuf->Flush(OutBuf, NumWritten);
+
+ if(EChar == IIO_ECHO_KILL) {
+ if(LFlags == ECHOK) {
+ NumWritten = IIO_WriteOne(filp, OutBuf, CHAR_LINEFEED);
+ }
+ else if((LFlags & ECHOE) && EchoIsOK) {
+ // Position the cursor to the start of input.
+ (void)IIO_SetCursorPosition(filp, &This->InitialXY);
+ }
+ NumWritten = 0;
+ }
+ }
+ else {
+ errno = EINVAL;
+ }
+
+ return NumWritten;
+}
+
+static
+void
+FifoDelete(cFIFO *Member)
+{
+ if(Member != NULL) {
+ Member->Delete(Member);
+ }
+}
+
+/** Destructor for an IIO instance.
+
+ Releases all resources used by a particular IIO instance.
+**/
+static
+void
+EFIAPI
+IIO_Delete(
+ cIIO *Self
+ )
+{
+ if(Self != NULL) {
+ FifoDelete(Self->ErrBuf);
+ FifoDelete(Self->OutBuf);
+ FifoDelete(Self->InBuf);
+ if(Self->AttrBuf != NULL) {
+ FreePool(Self->AttrBuf);
+ }
+ FreePool(Self);
+ }
+}
+
+/** Constructor for new IIO instances.
+
+ @return Returns NULL or a pointer to a new IIO instance.
+**/
+cIIO *
+EFIAPI
+New_cIIO(void)
+{
+ cIIO *IIO;
+ cc_t *TempBuf;
+ int i;
+
+ IIO = (cIIO *)AllocateZeroPool(sizeof(cIIO));
+ if(IIO != NULL) {
+ IIO->InBuf = New_cFIFO(MAX_INPUT, sizeof(wchar_t));
+ IIO->OutBuf = New_cFIFO(MAX_OUTPUT, sizeof(wchar_t));
+ IIO->ErrBuf = New_cFIFO(MAX_OUTPUT, sizeof(wchar_t));
+ IIO->AttrBuf = (UINT8 *)AllocateZeroPool(MAX_OUTPUT);
+
+ if((IIO->InBuf == NULL) || (IIO->OutBuf == NULL) ||
+ (IIO->ErrBuf == NULL) || (IIO->AttrBuf == NULL))
+ {
+ IIO_Delete(IIO);
+ IIO = NULL;
+ }
+ else {
+ IIO->Delete = IIO_Delete;
+ IIO->Read = IIO_Read;
+ IIO->Write = IIO_Write;
+ IIO->Echo = IIO_Echo;
+ }
+ // Initialize Termio member
+ TempBuf = &IIO->Termio.c_cc[0];
+ TempBuf[0] = 8; // Default length for TABs
+ for(i=1; i < NCCS; ++i) {
+ TempBuf[i] = _POSIX_VDISABLE;
+ }
+ TempBuf[VMIN] = 0;
+ TempBuf[VTIME] = 0;
+ IIO->Termio.c_ispeed = B115200;
+ IIO->Termio.c_ospeed = B115200;
+ IIO->Termio.c_iflag = ICRNL;
+ IIO->Termio.c_oflag = OPOST | ONLCR | ONOCR | ONLRET;
+ IIO->Termio.c_cflag = 0;
+ IIO->Termio.c_lflag = ECHO | ECHONL;
+ }
+ return IIO;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIO.inf b/StdLib/LibC/Uefi/InteractiveIO/IIO.inf
new file mode 100644
index 0000000000..dd21e85b13
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/IIO.inf
@@ -0,0 +1,51 @@
+## @file
+# Interactive I/O Library.
+#
+# Copyright (c) 2012, 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
+# http://opensource.org/licenses/bsd-license.php.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = LibIIO
+ FILE_GUID = c1e9fffb-5557-4cb5-a5f5-1fbd902a74ed
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = LibIIO
+
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ IIO.c
+ NonCanonRead.c
+ CanonRead.c
+ TerminalFunctions.c
+ IIOutilities.c
+ IIOwrite.c
+ IIOecho.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ StdLib/StdLib.dec
+ StdLibPrivateInternalFiles/DoNotUse.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ LibC
+ LibWchar
+ LibContainer
+
+[Protocols]
+ gEfiSimpleTextInProtocolGuid ## CONSUMES
+ gEfiSimpleTextOutProtocolGuid ## CONSUMES
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOecho.c b/StdLib/LibC/Uefi/InteractiveIO/IIOecho.c
new file mode 100644
index 0000000000..14369de95b
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/IIOecho.c
@@ -0,0 +1,141 @@
+/** @file
+ Echo characters to an Interactive I/O Output device.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+ Since the UEFI console is a WIDE character device, these functions do all
+ processing using wide characters.
+
+ It is the responsibility of the caller, or higher level function, to perform
+ any necessary translation between wide and narrow characters.
+
+ Copyright (c) 2012, 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
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <Uefi.h>
+
+#include <LibConfig.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include "IIOutilities.h"
+#include "IIOechoCtrl.h"
+
+/** Echo one character to an IIO file.
+
+ If character InCh is a special "echo control" character, process it and output
+ the resultant character(s), if any. Otherwise pass the character on to the
+ IIO_WriteOne() function which performs generic output processing, if needed.
+
+ @param[in] filp Pointer to an open IIO file's file descriptor structure.
+ @param[in] InCh The wide character to be echoed.
+ @param[in] EchoIsOK A flag indicating whether echoing is appropriate for this
+ device or not.
+
+ @retval -1 The filp argument does not refer to an IIO device.
+ Global value errno is set to EINVAL.
+ @retval >=0 The number of characters actually output.
+
+ @sa IIO_WriteOne
+**/
+ssize_t
+IIO_EchoOne (
+ struct __filedes *filp,
+ wchar_t InCh,
+ BOOLEAN EchoIsOK
+ )
+{
+ cIIO *This;
+ cFIFO *OutBuf;
+ cFIFO *InBuf;
+ UINT8 *AttrBuf;
+ ssize_t NumEcho;
+ tcflag_t LFlags;
+ UINT32 AttrDex;
+ int i;
+
+ NumEcho = -1;
+ This = filp->devdata;
+
+ if(This != NULL) {
+ LFlags = This->Termio.c_lflag;
+ OutBuf = This->OutBuf;
+ InBuf = This->InBuf;
+ AttrBuf = This->AttrBuf;
+ AttrDex = InBuf->GetWDex(InBuf);
+
+ switch(InCh) {
+ case IIO_ECHO_DISCARD:
+ // Do not buffer or otherwise process
+ NumEcho = 0;
+ break;
+
+ case IIO_ECHO_ERASE:
+ // Delete last character from InBuf
+ if(!InBuf->IsEmpty(InBuf)) {
+ (void)InBuf->Truncate(InBuf);
+
+ // Erase screen character(s) based on Attrib value
+ if(LFlags & ECHO) {
+ AttrDex = (UINT32)ModuloDecrement(AttrDex, InBuf->NumElements);
+ NumEcho = AttrBuf[AttrDex];
+ for(i = 0; i < NumEcho; ++i) {
+ (void)IIO_WriteOne(filp, OutBuf, CHAR_BACKSPACE);
+ }
+ if(LFlags & ECHOE) {
+ for(i = 0; i < NumEcho; ++i) {
+ (void)IIO_WriteOne(filp, OutBuf, L' ');
+ }
+ for(i = 0; i < NumEcho; ++i) {
+ (void)IIO_WriteOne(filp, OutBuf, CHAR_BACKSPACE);
+ }
+ }
+ }
+ else {
+ NumEcho = 0;
+ }
+ }
+ break;
+
+ case IIO_ECHO_KILL:
+ // Flush contents of InBuf and OutBuf
+ InBuf->Flush(InBuf, (size_t)-1);
+ OutBuf->Flush(OutBuf, (size_t)-1);
+
+ // Erase characters from screen.
+ if(LFlags & ECHOE) {
+ NumEcho = IIO_CursorDelta(This, &This->InitialXY, &This->CurrentXY);
+ for(i = 0; i < NumEcho; ++i) {
+ (void)IIO_WriteOne(filp, OutBuf, L' ');
+ }
+ }
+ break;
+
+ default:
+ // Add character to input buffer
+ (void)InBuf->Write(InBuf, &InCh, 1);
+
+ NumEcho = 0; // In case echoing is not enabled or OK
+ // If echoing is OK and enabled, "echo" character using IIO_WriteOne
+ if( EchoIsOK &&
+ ( (LFlags & ECHO) ||
+ ((LFlags & ECHONL) && (InCh == CHAR_LINEFEED))))
+ {
+ NumEcho = IIO_WriteOne(filp, OutBuf, InCh);
+ }
+ AttrBuf[AttrDex] = (UINT8)NumEcho;
+ break;
+ }
+ }
+ else {
+ errno = EINVAL;
+ }
+ return NumEcho;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h b/StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h
new file mode 100644
index 0000000000..69d040af01
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/IIOechoCtrl.h
@@ -0,0 +1,33 @@
+/** @file
+ Constants and declarations for the Echo function.
+
+ Copyright (c) 2012, 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
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef _IIO_ECHO_CTRL_H
+#define _IIO_ECHO_CTRL_H
+#include <sys/termios.h>
+
+__BEGIN_DECLS
+
+/* These constants are assigned values within the Unicode Private Use range.
+ The value of IIO_ECHO_MIN must be adjusted to ensure that IIO_ECHO_MAX
+ never exceeds the value of 0xF900.
+*/
+typedef enum {
+ IIO_ECHO_MIN = (TtyFunKeyMin - 3),
+ IIO_ECHO_DISCARD = IIO_ECHO_MIN, // Ignore this character completely
+ IIO_ECHO_ERASE, // Erase previous character
+ IIO_ECHO_KILL, // Kill the entire line
+ IIO_ECHO_MAX
+} IioEchoCtrl;
+
+__END_DECLS
+
+#endif /* _IIO_ECHO_CTRL_H */
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c b/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c
new file mode 100644
index 0000000000..2da0628840
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c
@@ -0,0 +1,288 @@
+/** @file
+ Utilities for Interactive I/O Functions.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+
+ Copyright (c) 2012, 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
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <Uefi.h>
+#include <Protocol/SimpleTextOut.h>
+
+#include <LibConfig.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <MainData.h>
+#include "IIOutilities.h"
+
+/** Get the low-level UEFI protocol associated with an open file.
+
+ @param[in] fd File descriptor for an open file.
+ @param[out] filp NULL, or a pointer to where a pointer to the file's
+ file descriptor structure is to be stored.
+
+ @return Returns NULL if fd is not a valid file descriptor, otherwise
+ a pointer to the file's associated UEFI protocol is returned.
+**/
+void *
+EFIAPI
+IIO_GetDeviceProto (
+ int fd,
+ struct __filedes **filp
+ )
+{
+ void *Proto;
+ ConInstance *Stream;
+ struct __filedes *pfil;
+
+ Proto = NULL;
+ if(ValidateFD( fd, VALID_OPEN)) {
+ pfil = &gMD->fdarray[fd];
+ Stream = BASE_CR(pfil->f_ops, ConInstance, Abstraction);
+ Proto = (void *)Stream->Dev;
+ if(filp != NULL) {
+ *filp = pfil;
+ }
+ }
+ return Proto;
+}
+
+/** Get a character either from the input buffer or from hardware.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[in] First Set to TRUE to identify the initial read.
+
+ @return Returns a character read from either the input buffer
+ or from the open file (device) identified by filp.
+ A return value of WEOF indicates an error has occurred.
+**/
+wint_t
+EFIAPI
+IIO_GetInChar (
+ struct __filedes *filp,
+ BOOLEAN First
+)
+{
+ cIIO *This;
+ cFIFO *InBuf;
+ EFI_STATUS Status;
+ ssize_t NumRead;
+ wint_t RetVal;
+ wchar_t InChar;
+
+ static size_t BufCnt;
+
+ This = filp->devdata;
+ InBuf = This->InBuf;
+
+ NumRead = -1;
+ InChar = 0;
+ if(First) {
+ BufCnt = InBuf->Count(InBuf, AsElements);
+ }
+ if(BufCnt > 0) {
+ Status = InBuf->Read(InBuf, &InChar, 1);
+ --BufCnt;
+ NumRead = 1;
+ }
+ else {
+ NumRead = filp->f_ops->fo_read(filp, &filp->f_offset, sizeof(wchar_t), &InChar);
+ }
+ if(NumRead <= 0) {
+ RetVal = WEOF;
+ }
+ else {
+ RetVal = (wint_t)InChar;
+ }
+ return InChar;
+}
+
+/** Get the current cursor position.
+
+ @param[in] fd File descriptor for an open file.
+ @param[out] Column Pointer to where the current cursor column is to be stored.
+ @param[out] Row Pointer to where the current cursor row is to be stored.
+
+ @retval -1 fd is not an IIO output device.
+ @retval 0 Cursor position retrieved, Cursor is Not Visible.
+ @retval 1 Cursor position retrieved, Cursor is Visible.
+**/
+int
+EFIAPI
+IIO_GetCursorPosition (
+ int fd,
+ UINT32 *Column,
+ UINT32 *Row
+ )
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
+ struct __filedes *pStdOut;
+ int RetVal;
+
+ RetVal = -1;
+
+ Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut);
+ if(Proto != NULL) {
+ if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY
+ ((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output
+ {
+ // fd is for a TTY or "Interactive IO" device
+ *Column = Proto->Mode->CursorColumn;
+ *Row = Proto->Mode->CursorRow;
+ if(Proto->Mode->CursorVisible) {
+ RetVal = 1;
+ }
+ else {
+ RetVal = 0;
+ }
+ }
+ }
+ return RetVal;
+}
+
+/** Set the cursor position.
+
+ @param[in] filp Pointer to the output device's file descriptor structure.
+ @param[in] StartXY Pointer to a cursor coordinate (XY) structure indicating
+ the desired coordinate to move the cursor to.
+
+ @retval -1 fd is not an IIO output device
+ @retval 0 Cursor position set successfully.
+**/
+int
+EFIAPI
+IIO_SetCursorPosition (
+ struct __filedes *filp,
+ CURSOR_XY *CursorXY
+ )
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
+ cIIO *This;
+ EFI_STATUS Status;
+ int RetVal;
+
+ RetVal = -1;
+
+ This = filp->devdata;
+ Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(filp->MyFD, NULL);
+ if(Proto != NULL) {
+ if(((filp->f_iflags & _S_ITTY) != 0) && // file is a TTY
+ ((filp->Oflags & O_ACCMODE) != 0)) // and it is open for output
+ {
+ // fd is for a TTY or "Interactive IO" device
+ Status = Proto->SetCursorPosition(Proto, CursorXY->Column, CursorXY->Row);
+ if(Status == EFI_SUCCESS) {
+ This->CurrentXY.Column = CursorXY->Column;
+ This->CurrentXY.Row = CursorXY->Row;
+ RetVal = 0;
+ }
+ }
+ }
+ return RetVal;
+}
+
+/** Get Output screen size and mode.
+
+ @param[in] fd File descriptor of the output device.
+ @param[out] Col Pointer to where to store the MAX Column, or NULL.
+ @param[out] Row Pointer to where to store the MAX Row, or NULL.
+
+ @retval <0 An error occurred. The reason is in errno and EFIerrno.
+ * EIO UEFI QueryMode failed
+ * ENOTTY fd does not refer to an interactive output device
+ @retval >=0 Current output mode
+**/
+int
+EFIAPI
+IIO_GetOutputSize (
+ int fd,
+ UINTN *Col,
+ UINTN *Row
+)
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto;
+ struct __filedes *pStdOut;
+ EFI_STATUS Status;
+ UINTN TempCol;
+ UINTN TempRow;
+ UINTN TempMode;
+ int RetVal;
+
+ RetVal = -1;
+
+ Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut);
+ if(Proto != NULL) {
+ if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY
+ ((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output
+ {
+ // fd is for a TTY or "Interactive IO" device
+ TempMode = Proto->Mode->Mode;
+ Status = Proto->QueryMode(Proto, TempMode, &TempCol, &TempRow);
+ if(EFI_ERROR(Status)) {
+ EFIerrno = Status;
+ errno = EIO;
+ }
+ else {
+ *Col = TempCol;
+ *Row = TempRow;
+ RetVal = (int)TempMode;
+ }
+ }
+ else {
+ errno = ENOTTY;
+ }
+ }
+ return RetVal;
+}
+
+/** Calculate the number of character positions between two X/Y coordinate pairs.
+
+ Using the current output device characteristics, calculate the number of
+ characters between two coordinates. It is assumed that EndXY points to
+ an output location that occurs after StartXY.
+
+ RowDelta is the computed difference between the ending and starting rows.
+ If RowDelta < 0, then EndXY is NOT after StartXY, so assert.
+
+ ColumnDelta is the computed number of character positions (columns) between
+ the starting position and the ending position. If ColumnDelta is < 0,
+ then EndXY is NOT after StartXY, so assert.
+
+ @param[in] This Pointer to the IIO instance to be examined.
+ @param[in] StartXY Pointer to the starting coordinate pair.
+ @param[in] EndXY Pointer to the ending coordinate pair.
+
+ @return Returns the difference between the starting and ending coordinates.
+**/
+UINT32
+EFIAPI
+IIO_CursorDelta (
+ cIIO *This,
+ CURSOR_XY *StartXY,
+ CURSOR_XY *EndXY
+)
+{
+ INT32 ColumnDelta;
+ INT32 RowDelta;
+
+ RowDelta = (int)EndXY->Row - (int)StartXY->Row;
+
+ assert(RowDelta >= 0); // assert if EndXY is NOT after StartXY
+
+ ColumnDelta = (INT32)((This->MaxColumn * RowDelta) + EndXY->Column);
+ ColumnDelta -= (INT32)StartXY->Column;
+
+ assert(ColumnDelta >= 0); // assert if EndXY is NOT after StartXY
+
+ return (UINT32)ColumnDelta;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h b/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h
new file mode 100644
index 0000000000..778b612ea5
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.h
@@ -0,0 +1,129 @@
+/** @file
+ Utilities for Interactive I/O Functions.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+
+ Copyright (c) 2012, 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
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef _IIO_UTILITIES_H
+#define _IIO_UTILITIES_H
+
+#include <sys/EfiSysCall.h>
+
+__BEGIN_DECLS
+
+/** Get the low-level UEFI protocol associated with an open file.
+
+ @param[in] fd File descriptor for an open file.
+ @param[out] filp NULL, or a pointer to where a pointer to the file's
+ file descriptor structure is to be stored.
+
+ @return Returns NULL if fd is not a valid file descriptor, otherwise
+ a pointer to the file's associated UEFI protocol is returned.
+**/
+void *
+EFIAPI
+IIO_GetDeviceProto (
+ int fd,
+ struct __filedes **filp // Optional - filp == NULL if unused
+ );
+
+/** Get a character either from the input buffer or from hardware.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[in] First Set to TRUE to identify the initial read.
+
+ @return Returns a character read from either the input buffer
+ or from the open file (device) identified by filp.
+ A return value of WEOF indicates an error has occurred.
+**/
+wint_t
+EFIAPI
+IIO_GetInChar (
+ struct __filedes *filp,
+ BOOLEAN First
+ );
+
+/** Get the current cursor position.
+
+ @param[in] fd File descriptor for an open file.
+ @param[out] Column Pointer to where the current cursor column is to be stored.
+ @param[out] Row Pointer to where the current cursor row is to be stored.
+
+ @retval -1 fd is not an IIO output device.
+ @retval 0 Cursor position retrieved, Cursor is Not Visible.
+ @retval 1 Cursor position retrieved, Cursor is Visible.
+**/
+int
+EFIAPI
+IIO_GetCursorPosition (
+ int fd,
+ UINT32 *Column,
+ UINT32 *Row
+ );
+
+/** Set the cursor position.
+
+ @param[in] filp Pointer to the output device's file descriptor structure.
+ @param[in] StartXY Pointer to a cursor coordinate (XY) structure indicating
+ the desired coordinate to move the cursor to.
+
+ @retval -1 fd is not an IIO output device
+ @retval 0 Cursor position set successfully.
+**/
+int
+EFIAPI
+IIO_SetCursorPosition (
+ struct __filedes *filp,
+ CURSOR_XY *StartXY
+ );
+
+/** Get Output screen size and mode.
+
+ @param[in] fd File descriptor of the output device.
+ @param[out] Col Pointer to where to store the MAX Column, or NULL.
+ @param[out] Row Pointer to where to store the MAX Row, or NULL.
+
+ @retval <0 An error occurred. The reason is in errno and EFIerrno.
+ * EIO UEFI QueryMode failed
+ * ENOTTY fd does not refer to an interactive output device
+ @retval >=0 Current output mode
+**/
+int
+EFIAPI
+IIO_GetOutputSize (
+ int fd,
+ UINTN *Col,
+ UINTN *Row
+);
+
+/** Calculate the number of character positions between two X/Y coordinate pairs.
+
+ Using the current output device characteristics, calculate the number of
+ characters between two coordinates.
+
+ @param[in] This Pointer to the IIO instance to be examined.
+ @param[in] StartXY Pointer to the starting coordinate pair.
+ @param[in] EndXY Pointer to the ending coordinate pair.
+
+ @return Returns the difference between the starting and ending coordinates.
+ The return value is positive if the coordinates contained in EndXY
+ are larger than StartXY, otherwise the return value is negative.
+**/
+int
+EFIAPI
+IIO_CursorDelta (
+ cIIO *This,
+ CURSOR_XY *StartXY,
+ CURSOR_XY *EndXY
+ );
+
+__END_DECLS
+#endif /* _IIO_UTILITIES_H */
diff --git a/StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c b/StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c
new file mode 100644
index 0000000000..927f4f4ff3
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/IIOwrite.c
@@ -0,0 +1,210 @@
+/** @file
+ Write to an Interactive I/O Output device.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+ Since the UEFI console is a WIDE character device, these functions do all
+ processing using wide characters.
+
+ It is the responsibility of the caller, or higher level function, to perform
+ any necessary translation between wide and narrow characters.
+
+ Copyright (c) 2012, 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
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <Uefi.h>
+
+#include <LibConfig.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+
+static wchar_t Spaces[] = L" "; // Spaces for expanding TABs
+
+#define MAX_TAB_WIDTH ((int)(sizeof(Spaces) / sizeof(wchar_t)) - 1)
+
+#define MAX_EXPANSION 3
+
+/** Process and buffer one character for output.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[out] OBuf Pointer to the Output Buffer FIFO.
+ @param[in] InCh The wide character to process.
+
+ @retval <0 An error occurred. Reason is in errno.
+ * EINVAL The pointer to the IIO object is NULL.
+ * ENOSPC The OBuf FIFO is full.
+
+ @retval 0 A character was input but not placed in the output buffer.
+
+ @retval >0 The number of characters buffered. Normally 1, or 2.
+ If a character is discarded because of flag settings, a
+ 1 will be returned.
+**/
+ssize_t
+IIO_WriteOne(struct __filedes *filp, cFIFO *OBuf, wchar_t InCh)
+{
+ cIIO *This;
+ struct termios *Termio;
+ tcflag_t OFlag;
+ ssize_t RetVal;
+ wchar_t wc[MAX_EXPANSION]; // Sub-buffer for conversions
+ wchar_t *wcb; // Pointer to either wc or spaces
+ int numW = 0; // Wide characters placed in OBuf
+ INT32 TabWidth; // Each TAB expands into this number of spaces
+ UINT32 CurColumn; // Current cursor column on the screen
+ UINT32 CurRow; // Current cursor row on the screen
+ UINT32 PrevColumn; // Previous column. Used to detect wrapping.
+ UINT32 AdjColumn; // Current cursor column on the screen
+ UINT32 AdjRow; // Current cursor row on the screen
+
+ RetVal = -1;
+ wcb = wc;
+ This = filp->devdata;
+ if((This != NULL) && (OBuf->FreeSpace(OBuf, AsElements) >= MAX_EXPANSION)) {
+ Termio = &This->Termio;
+ OFlag = Termio->c_oflag;
+ TabWidth = (INT32)This->Termio.c_cc[VTABLEN];
+ if(TabWidth > MAX_TAB_WIDTH) {
+ TabWidth = MAX_TAB_WIDTH;
+ }
+ CurColumn = This->CurrentXY.Column;
+ CurRow = This->CurrentXY.Row;
+
+ numW = 1; // The majority of characters buffer one character
+ AdjRow = 0; // Most characters just cause horizontal movement
+ AdjColumn = 0;
+ if(OFlag & OPOST) {
+ /* Perform output processing */
+ switch(InCh) {
+ case CHAR_TAB: //{{
+ if(OFlag & OXTABS) {
+ if(TabWidth > 0) {
+ int SpaceIndex;
+
+ SpaceIndex = CurColumn % TabWidth; // Number of spaces after a Tab Stop
+ numW = TabWidth - SpaceIndex; // Number of spaces to the next Tab Stop
+ SpaceIndex = MAX_TAB_WIDTH - numW; // Index into the Spaces array
+ wcb = &Spaces[SpaceIndex]; // Point to the appropriate number of spaces
+ }
+ else {
+ wc[0] = L' ';
+ }
+ AdjColumn = numW;
+ }
+ else {
+ wc[0] = InCh; // Send the TAB itself - assumes that it does not move cursor.
+ }
+ break; //}}
+
+ case CHAR_CARRIAGE_RETURN: //{{
+ if((OFlag & OCRNL) == 0) {
+ if((OFlag & ONLRET) == 0) {
+ numW = 0; /* Discard the CR */
+ // Cursor doesn't move
+ }
+ else {
+ wc[0] = CHAR_CARRIAGE_RETURN;
+ CurColumn = 0;
+ }
+ break;
+ }
+ else {
+ InCh = CHAR_LINEFEED;
+ } //}}
+ // Fall through to the NL case
+ case CHAR_LINEFEED: //{{
+ if(OFlag & ONLCR) {
+ wc[0] = CHAR_CARRIAGE_RETURN;
+ wc[1] = CHAR_LINEFEED;
+ numW = 2;
+ CurColumn = 0;
+ }
+ AdjRow = 1;
+ break; //}}
+
+ case CHAR_BACKSPACE: //{{
+ if(CurColumn > 0) {
+ wc[0] = CHAR_BACKSPACE;
+ CurColumn = (UINT32)ModuloDecrement(CurColumn, (UINT32)This->MaxColumn);
+ }
+ else {
+ numW = 0; // Discard the backspace if in column 0
+ }
+ break; //}}
+
+ case CHAR_EOT: //{{
+ if(OFlag & ONOEOT) {
+ numW = 0; // Discard the EOT character
+ // Cursor doesn't move
+ break;
+ } //}}
+ // Fall through to default in order to potentially output "^D"
+ default: //{{
+ if((InCh >= 0) && (InCh < L' ')) {
+ // InCh contains a control character
+ if(OFlag & OCTRL) {
+ wc[1] = InCh + L'@';
+ wc[0] = L'^';
+ numW = 2;
+ AdjColumn = 2;
+ }
+ else {
+ numW = 0; // Discard. Not a UEFI supported control character.
+ }
+ }
+ else {
+ // Regular printing character
+ wc[0] = InCh;
+ AdjColumn = 1;
+ }
+ break; //}}
+ }
+ if(numW < MAX_EXPANSION) {
+ wc[numW] = 0; // Terminate the sub-buffer
+ }
+ if(AdjColumn != 0) {
+ // Adjust the cursor position
+ PrevColumn = CurColumn;
+ CurColumn = ModuloAdd(PrevColumn, AdjColumn, (UINT32)This->MaxColumn);
+ if(CurColumn < PrevColumn) {
+ // We must have wrapped, so we are on the next Row
+ ++CurRow;
+ if(CurRow >= This->MaxRow) {
+ // The screen has scrolled so need to adjust Initial location.
+ --This->InitialXY.Row; // Initial row has moved up one
+ CurRow = (UINT32)(This->MaxRow - 1); // We stay on the bottom row
+ }
+ }
+ }
+ This->CurrentXY.Column = CurColumn;
+ This->CurrentXY.Row = CurRow;
+ }
+ else {
+ // Output processing disabled -- RAW output mode
+ wc[0] = InCh;
+ wc[1] = 0;
+ }
+ // Put the character(s) into the output buffer
+ if(numW > 0) {
+ (void)OBuf->Write(OBuf, (const void *)wcb, (size_t)numW);
+ }
+ RetVal = numW;
+ }
+ else {
+ if(This == NULL) {
+ errno = EINVAL;
+ }
+ else {
+ errno = ENOSPC;
+ }
+ }
+ return RetVal;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c b/StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c
new file mode 100644
index 0000000000..15bf43e260
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/NonCanonRead.c
@@ -0,0 +1,89 @@
+/** @file
+ NonCanonical Interactive Input Function.
+
+ The functions assume that isatty() is TRUE at the time they are called.
+ If _S_IWTTY is set, the device returns WIDE characters.
+
+ Copyright (c) 2012, 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
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <LibConfig.h>
+
+#include <sys/syslimits.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <Containers/Fifo.h>
+
+/** Perform a noncanonical read of input.
+
+ @param[in] filp Pointer to a file descriptor structure.
+ @param[in] BufferSize Maximum number of bytes to return.
+
+ @retval -1 An error has occurred. Reason in errno.
+ @retval -1 No data returned. None was ready.
+ @retval >0 The number of elements returned
+**/
+ssize_t
+IIO_NonCanonRead (
+ struct __filedes *filp
+ )
+{
+ cIIO *This;
+ cFIFO *InBuf;
+ struct termios *Termio;
+ EFI_STATUS Status;
+ ssize_t NumRead;
+ cc_t tioMin;
+ cc_t tioTime;
+ UINT32 InputType;
+ wchar_t InChar; // Intermediate character buffer
+
+ NumRead = -1;
+ InChar = 0; // Initialize so compilers don't complain.
+ This = filp->devdata;
+ Termio = &This->Termio;
+ InBuf = This->InBuf;
+ tioMin = Termio->c_cc[VMIN];
+ tioTime = Termio->c_cc[VTIME];
+
+ if(tioMin >= MAX_INPUT) {
+ tioMin = MAX_INPUT;
+ }
+ /* There are four types of processing that may be done, based on
+ the values of tioMin and tioTime.
+ Min Time Type
+ --- ---- ----
+ 0 0 0 Return buffer contents or 1 new char
+ 0 >0 1 Return 0 or 1 character depending on timeout
+ >0 0 2 Buffer Min chars. Return BufferSize chars.
+ >0 >0 3 Return up to Min chars. Unless the inter-byte timer expires.
+
+ Currently, only type 0 is implemented.
+ */
+ InputType = 0;
+ if(tioMin != 0) InputType = 2;
+ if(tioTime != 0) ++InputType;
+ //switch(InputType) {
+ // case 0:
+ if(InBuf->IsEmpty(InBuf)) {
+ NumRead = filp->f_ops->fo_read(filp, &filp->f_offset, sizeof(wchar_t), &InChar);
+ if(NumRead > 0) {
+ Status = InBuf->Write(InBuf, &InChar, 1); // Buffer the character
+ }
+ }
+ // break;
+ // case 1:
+ // break;
+ // case 2:
+ // break;
+ // case 3:
+ // break;
+ //}
+ return NumRead;
+}
diff --git a/StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c b/StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c
new file mode 100644
index 0000000000..807ab1fd4c
--- /dev/null
+++ b/StdLib/LibC/Uefi/InteractiveIO/TerminalFunctions.c
@@ -0,0 +1,285 @@
+/** @file
+ "Terminal" Control functions for Interactive IO.
+
+ Copyright (c) 2012, 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.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <LibConfig.h>
+
+#include <errno.h>
+#include <sys/termios.h>
+#include <Device/IIO.h>
+#include <MainData.h>
+
+/** Get input baud rate.
+
+ Extracts the input baud rate from the termios structure pointed to by the
+ pTermios argument.
+
+ @param[in] pTermios A pointer to the termios structure from which to extract
+ the input baud rate.
+
+ @return The value of the input speed is returned exactly as it is contained
+ in the termios structure, without interpretation.
+**/
+speed_t
+cfgetispeed (
+ const struct termios *pTermios
+ )
+{
+ return pTermios->c_ispeed;
+}
+
+/** Get output baud rate.
+
+ Extracts the output baud rate from the termios structure pointed to by the
+ pTermios argument.
+
+ @param[in] pTermios A pointer to the termios structure from which to extract
+ the output baud rate.
+
+ @return The value of the output speed is returned exactly as it is contained
+ in the termios structure, without interpretation.
+**/
+speed_t
+cfgetospeed (
+ const struct termios *pTermios
+ )
+{
+ return pTermios->c_ospeed;
+}
+
+/** Set input baud rate.
+
+ Replaces the input baud rate, in the termios structure pointed to by the
+ pTermios argument, with the value of NewSpeed.
+
+ @param[out] pTermios A pointer to the termios structure into which to set
+ the input baud rate.
+ @param[in] NewSpeed The new input baud rate.
+
+ @retval 0 The operation completed successfully.
+ @retval -1 An error occured and errno is set to indicate the error.
+ * EINVAL - The value of NewSpeed is outside the range of
+ possible speed values as specified in <sys/termios.h>.
+**/
+int
+cfsetispeed (
+ struct termios *pTermios,
+ speed_t NewSpeed
+ )
+{
+ int RetVal;
+
+ if(NewSpeed < B921600) {
+ pTermios->c_ispeed = NewSpeed;
+ RetVal = 0;
+ }
+ else {
+ RetVal = -1;
+ errno = EINVAL;
+ }
+ return RetVal;
+}
+
+/** Set output baud rate.
+
+ Replaces the output baud rate, in the termios structure pointed to by the
+ pTermios argument, with the value of NewSpeed.
+
+ @param[out] pTermios A pointer to the termios structure into which to set
+ the output baud rate.
+ @param[in] NewSpeed The new output baud rate.
+
+ @retval 0 The operation completed successfully.
+ @retval -1 An error occured and errno is set to indicate the error.
+ * EINVAL - The value of NewSpeed is outside the range of
+ possible speed values as specified in <sys/termios.h>.
+**/
+int
+cfsetospeed (
+ struct termios *pTermios,
+ speed_t NewSpeed
+ )
+{
+ int RetVal;
+
+ if(NewSpeed < B921600) {
+ pTermios->c_ospeed = NewSpeed;
+ RetVal = 0;
+ }
+ else {
+ RetVal = -1;
+ errno = EINVAL;
+ }
+ return RetVal;
+}
+
+/** Get the parameters associated with an interactive IO device.
+
+ Get the parameters associated with the device referred to by
+ fd and store them into the termios structure referenced by pTermios.
+
+ @param[in] fd The file descriptor for an open interactive IO device.
+ @param[out] pTermios A pointer to a termios structure into which to store
+ attributes of the interactive IO device.
+
+ @retval 0 The operation completed successfully.
+ @retval -1 An error occured and errno is set to indicate the error.
+ * EBADF - The fd argument is not a valid file descriptor.
+ * ENOTTY - The file associated with fd is not an interactive IO device.
+**/
+int
+tcgetattr (
+ int fd,
+ struct termios *pTermios
+ )
+{
+ cIIO *IIO;
+ int RetVal;
+ struct __filedes *filp;
+ struct termios *Termio;
+
+ RetVal = 0;
+ if(ValidateFD( fd, VALID_OPEN)) {
+ filp = &gMD->fdarray[fd];
+
+ if((filp->f_iflags & _S_ITTY) != 0) {
+ // fd is for a TTY or "Interactive IO" device
+ IIO = (cIIO *)filp->devdata;
+ Termio = &IIO->Termio;
+ (void)CopyMem((void *)pTermios, (const void *)Termio, sizeof(struct termios));
+ }
+ else {
+ errno = ENOTTY;
+ RetVal = -1;
+ }
+ }
+ else {
+ errno = EBADF;
+ RetVal = -1;
+ }
+ return RetVal;
+}
+
+/** Set the parameters associated with an interactive IO device.
+
+ Set the parameters associated with the device referred to by
+ fd to the values in the termios structure referenced by pTermios.
+
+ Behavior is modified by the value of the OptAct parameter:
+ * TCSANOW: The change shall occur immediately.
+ * TCSADRAIN: The change shall occur after all output written to fd is
+ transmitted. This action should be used when changing parameters which
+ affect output.
+ * TCSAFLUSH: The change shall occur after all output written to fd is
+ transmitted, and all input so far received but not read shall be
+ discarded before the change is made.
+
+ @param[in] fd The file descriptor for an open interactive IO device.
+ @param[in] OptAct Currently has no effect.
+ @param[in] pTermios A pointer to a termios structure into which to retrieve
+ attributes to set in the interactive IO device.
+
+ @retval 0 The operation completed successfully.
+ @retval -1 An error occured and errno is set to indicate the error.
+ * EBADF - The fd argument is not a valid file descriptor.
+ * ENOTTY - The file associated with fd is not an interactive IO device.
+**/
+int
+tcsetattr (
+ int fd,
+ int OptAct, // Currently ignored
+ const struct termios *pTermios
+ )
+{
+ cIIO *IIO;
+ int RetVal;
+ struct __filedes *filp;
+ struct termios *Termio;
+
+ RetVal = 0;
+ if(ValidateFD( fd, VALID_OPEN)) {
+ filp = &gMD->fdarray[fd];
+
+ if((filp->f_iflags & _S_ITTY) != 0) {
+ // fd is for a TTY or "Interactive IO" device
+ IIO = (cIIO *)filp->devdata;
+ Termio = &IIO->Termio;
+ (void)CopyMem((void *)Termio, (const void *)pTermios, sizeof(struct termios));
+ }
+ else {
+ errno = ENOTTY;
+ RetVal = -1;
+ }
+ }
+ else {
+ errno = EBADF;
+ RetVal = -1;
+ }
+ return RetVal;
+}
+
+/** Transmit pending output.
+
+ Function is not yet implemented for UEFI.
+
+ @param[in] fd Ignored
+
+ @retval -1 This function is not yet supported. errno is set to ENOTSUP.
+**/
+int
+tcdrain (int fd)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+/** Suspend or restart the transmission or reception of data.
+
+ This function will suspend or resume transmission or reception of data on
+ the file referred to by fd, depending on the value of Action.
+
+ Function is not yet implemented for UEFI.
+
+ @param[in] fd Ignored
+ @param[in] Action Ignored
+
+ @retval -1 This function is not yet supported. errno is set to ENOTSUP.
+**/
+int
+tcflow (
+ int fd,
+ int Action)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+
+/** Discard non-transmitted output data, non-read input data, or both.
+
+ Function is not yet implemented for UEFI.
+
+ @param[in] fd Ignored
+ @param[in] QueueSelector Ignored
+
+ @retval -1 This function is not yet supported. errno is set to ENOTSUP.
+**/
+int
+tcflush (
+ int fd,
+ int QueueSelector)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+