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
IIO_GetDeviceProto(int fd,struct __filedes ** filp)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
IIO_GetInChar(struct __filedes * filp,BOOLEAN First)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
IIO_GetCursorPosition(int fd,UINT32 * Column,UINT32 * Row)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
IIO_SetCursorPosition(struct __filedes * filp,CURSOR_XY * CursorXY)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
IIO_GetOutputSize(int fd,UINTN * Col,UINTN * Row)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
IIO_CursorDelta(cIIO * This,CURSOR_XY * StartXY,CURSOR_XY * EndXY)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