summaryrefslogtreecommitdiff
path: root/StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c
diff options
context:
space:
mode:
Diffstat (limited to 'StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c')
-rw-r--r--StdLib/LibC/Uefi/InteractiveIO/IIOutilities.c288
1 files changed, 288 insertions, 0 deletions
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;
+}