1 /** @file 2 Utilities for Interactive I/O Functions. 3 4 The functions assume that isatty() is TRUE at the time they are called. 5 6 Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR> 7 This program and the accompanying materials are licensed and made available 8 under the terms and conditions of the BSD License which accompanies this 9 distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php. 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 **/ 15 #include <Uefi.h> 16 #include <Protocol/SimpleTextOut.h> 17 18 #include <LibConfig.h> 19 20 #include <assert.h> 21 #include <errno.h> 22 #include <sys/syslimits.h> 23 #include <sys/termios.h> 24 #include <Device/IIO.h> 25 #include <MainData.h> 26 #include "IIOutilities.h" 27 28 /** Get the low-level UEFI protocol associated with an open file. 29 30 @param[in] fd File descriptor for an open file. 31 @param[out] filp NULL, or a pointer to where a pointer to the file's 32 file descriptor structure is to be stored. 33 34 @return Returns NULL if fd is not a valid file descriptor, otherwise 35 a pointer to the file's associated UEFI protocol is returned. 36 **/ 37 void * 38 EFIAPI 39 IIO_GetDeviceProto ( 40 int fd, 41 struct __filedes **filp 42 ) 43 { 44 void *Proto; 45 ConInstance *Stream; 46 struct __filedes *pfil; 47 48 Proto = NULL; 49 if(ValidateFD( fd, VALID_OPEN)) { 50 pfil = &gMD->fdarray[fd]; 51 Stream = BASE_CR(pfil->f_ops, ConInstance, Abstraction); 52 Proto = (void *)Stream->Dev; 53 if(filp != NULL) { 54 *filp = pfil; 55 } 56 } 57 return Proto; 58 } 59 60 /** Get a character either from the input buffer or from hardware. 61 62 @param[in] filp Pointer to a file descriptor structure. 63 @param[in] First Set to TRUE to identify the initial read. 64 65 @return Returns a character read from either the input buffer 66 or from the open file (device) identified by filp. 67 A return value of WEOF indicates an error has occurred. 68 **/ 69 wint_t 70 EFIAPI 71 IIO_GetInChar ( 72 struct __filedes *filp, 73 BOOLEAN First 74 ) 75 { 76 cIIO *This; 77 cFIFO *InBuf; 78 size_t Status; 79 ssize_t NumRead; 80 wint_t RetVal; 81 wchar_t InChar; 82 83 static size_t BufCnt; 84 85 This = filp->devdata; 86 InBuf = This->InBuf; 87 88 NumRead = -1; 89 InChar = 0; 90 if(First) { 91 BufCnt = InBuf->Count(InBuf, AsElements); 92 } 93 if(BufCnt > 0) { 94 Status = InBuf->Read(InBuf, &InChar, 1); 95 if (Status > 0) { 96 --BufCnt; 97 NumRead = 1; 98 } 99 } 100 else { 101 NumRead = filp->f_ops->fo_read(filp, &filp->f_offset, sizeof(wchar_t), &InChar); 102 } 103 if(NumRead <= 0) { 104 RetVal = WEOF; 105 } 106 else { 107 RetVal = (wint_t)InChar; 108 } 109 return RetVal; 110 } 111 112 /** Get the current cursor position. 113 114 @param[in] fd File descriptor for an open file. 115 @param[out] Column Pointer to where the current cursor column is to be stored. 116 @param[out] Row Pointer to where the current cursor row is to be stored. 117 118 @retval -1 fd is not an IIO output device. 119 @retval 0 Cursor position retrieved, Cursor is Not Visible. 120 @retval 1 Cursor position retrieved, Cursor is Visible. 121 **/ 122 int 123 EFIAPI 124 IIO_GetCursorPosition ( 125 int fd, 126 UINT32 *Column, 127 UINT32 *Row 128 ) 129 { 130 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto; 131 struct __filedes *pStdOut; 132 int RetVal; 133 134 RetVal = -1; 135 136 Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut); 137 if(Proto != NULL) { 138 if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY 139 ((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output 140 { 141 // fd is for a TTY or "Interactive IO" device 142 *Column = Proto->Mode->CursorColumn; 143 *Row = Proto->Mode->CursorRow; 144 if(Proto->Mode->CursorVisible) { 145 RetVal = 1; 146 } 147 else { 148 RetVal = 0; 149 } 150 } 151 } 152 return RetVal; 153 } 154 155 /** Set the cursor position. 156 157 @param[in] filp Pointer to the output device's file descriptor structure. 158 @param[in] StartXY Pointer to a cursor coordinate (XY) structure indicating 159 the desired coordinate to move the cursor to. 160 161 @retval -1 fd is not an IIO output device 162 @retval 0 Cursor position set successfully. 163 **/ 164 int 165 EFIAPI 166 IIO_SetCursorPosition ( 167 struct __filedes *filp, 168 CURSOR_XY *CursorXY 169 ) 170 { 171 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto; 172 cIIO *This; 173 EFI_STATUS Status; 174 int RetVal; 175 176 RetVal = -1; 177 178 This = filp->devdata; 179 Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(filp->MyFD, NULL); 180 if(Proto != NULL) { 181 if(((filp->f_iflags & _S_ITTY) != 0) && // file is a TTY 182 ((filp->Oflags & O_ACCMODE) != 0)) // and it is open for output 183 { 184 // fd is for a TTY or "Interactive IO" device 185 Status = Proto->SetCursorPosition(Proto, CursorXY->Column, CursorXY->Row); 186 if(Status == EFI_SUCCESS) { 187 This->CurrentXY.Column = CursorXY->Column; 188 This->CurrentXY.Row = CursorXY->Row; 189 RetVal = 0; 190 } 191 } 192 } 193 return RetVal; 194 } 195 196 /** Get Output screen size and mode. 197 198 @param[in] fd File descriptor of the output device. 199 @param[out] Col Pointer to where to store the MAX Column, or NULL. 200 @param[out] Row Pointer to where to store the MAX Row, or NULL. 201 202 @retval <0 An error occurred. The reason is in errno and EFIerrno. 203 * EIO UEFI QueryMode failed 204 * ENOTTY fd does not refer to an interactive output device 205 @retval >=0 Current output mode 206 **/ 207 int 208 EFIAPI 209 IIO_GetOutputSize ( 210 int fd, 211 UINTN *Col, 212 UINTN *Row 213 ) 214 { 215 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Proto; 216 struct __filedes *pStdOut; 217 EFI_STATUS Status; 218 UINTN TempCol; 219 UINTN TempRow; 220 UINTN TempMode; 221 int RetVal; 222 223 RetVal = -1; 224 225 Proto = (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)IIO_GetDeviceProto(fd, &pStdOut); 226 if(Proto != NULL) { 227 if(((pStdOut->f_iflags & _S_ITTY) != 0) && // file is a TTY 228 ((pStdOut->Oflags & O_ACCMODE) != 0)) // and it is open for output 229 { 230 // fd is for a TTY or "Interactive IO" device 231 TempMode = Proto->Mode->Mode; 232 Status = Proto->QueryMode(Proto, TempMode, &TempCol, &TempRow); 233 if(EFI_ERROR(Status)) { 234 EFIerrno = Status; 235 errno = EIO; 236 } 237 else { 238 *Col = TempCol; 239 *Row = TempRow; 240 RetVal = (int)TempMode; 241 } 242 } 243 else { 244 errno = ENOTTY; 245 } 246 } 247 return RetVal; 248 } 249 250 /** Calculate the number of character positions between two X/Y coordinate pairs. 251 252 Using the current output device characteristics, calculate the number of 253 characters between two coordinates. It is assumed that EndXY points to 254 an output location that occurs after StartXY. 255 256 RowDelta is the computed difference between the ending and starting rows. 257 If RowDelta < 0, then EndXY is NOT after StartXY, so assert. 258 259 ColumnDelta is the computed number of character positions (columns) between 260 the starting position and the ending position. If ColumnDelta is < 0, 261 then EndXY is NOT after StartXY, so assert. 262 263 @param[in] This Pointer to the IIO instance to be examined. 264 @param[in] StartXY Pointer to the starting coordinate pair. 265 @param[in] EndXY Pointer to the ending coordinate pair. 266 267 @return Returns the difference between the starting and ending coordinates. 268 The return value is positive if the coordinates contained in EndXY 269 are larger than StartXY, otherwise the return value is negative. 270 **/ 271 int 272 EFIAPI 273 IIO_CursorDelta ( 274 cIIO *This, 275 CURSOR_XY *StartXY, 276 CURSOR_XY *EndXY 277 ) 278 { 279 int ColumnDelta; 280 int RowDelta; 281 282 RowDelta = (int)EndXY->Row - (int)StartXY->Row; 283 284 assert(RowDelta >= 0); // assert if EndXY is NOT after StartXY 285 286 ColumnDelta = (int)((This->MaxColumn * RowDelta) + EndXY->Column); 287 ColumnDelta -= (int)StartXY->Column; 288 289 return ColumnDelta; 290 } 291