]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Application/Shell/ConsoleWrappers.c
ShellPkg: Fixes the shell so output redirection works for the 'mode' command
[mirror_edk2.git] / ShellPkg / Application / Shell / ConsoleWrappers.c
1 /** @file
2 Function definitions for shell simple text in and out on top of file handles.
3
4 Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
5 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Shell.h"
17
18 typedef struct {
19 EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn;
20 SHELL_FILE_HANDLE FileHandle;
21 EFI_HANDLE TheHandle;
22 } SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
23
24 typedef struct {
25 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOut;
26 SHELL_FILE_HANDLE FileHandle;
27 EFI_HANDLE TheHandle;
28 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalSimpleTextOut;
29 } SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
30
31 /**
32 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
33 Signal the event if there is key available
34
35 @param Event Indicates the event that invoke this function.
36 @param Context Indicates the calling context.
37
38 **/
39 VOID
40 EFIAPI
41 ConInWaitForKey (
42 IN EFI_EVENT Event,
43 IN VOID *Context
44 )
45 {
46 UINT64 Position;
47 UINT64 Size;
48 //
49 // Someone is waiting on the keystroke event, if there's
50 // a key pending, signal the event
51 //
52 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
53 //
54 ShellInfoObject.NewEfiShellProtocol->GetFilePosition(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Context)->FileHandle, &Position);
55 ShellInfoObject.NewEfiShellProtocol->GetFileSize (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Context)->FileHandle, &Size );
56 if (Position < Size) {
57 gBS->SignalEvent (Event);
58 }
59 }
60
61 /**
62 Reset function for the fake simple text input.
63
64 @param[in] This A pointer to the SimpleTextIn structure.
65 @param[in] ExtendedVerification TRUE for extra validation, FALSE otherwise.
66
67 @retval EFI_SUCCESS The reset was successful.
68 **/
69 EFI_STATUS
70 EFIAPI
71 FileBasedSimpleTextInReset(
72 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
73 IN BOOLEAN ExtendedVerification
74 )
75 {
76 return (EFI_SUCCESS);
77 }
78
79 /**
80 ReadKeyStroke function for the fake simple text input.
81
82 @param[in] This A pointer to the SimpleTextIn structure.
83 @param[in, out] Key A pointer to the Key structure to fill.
84
85 @retval EFI_SUCCESS The read was successful.
86 **/
87 EFI_STATUS
88 EFIAPI
89 FileBasedSimpleTextInReadKeyStroke(
90 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
91 IN OUT EFI_INPUT_KEY *Key
92 )
93 {
94 UINTN Size;
95 Size = sizeof(CHAR16);
96 if (Key == NULL || This == NULL) {
97 return (EFI_INVALID_PARAMETER);
98 }
99 Key->ScanCode = 0;
100 return (ShellInfoObject.NewEfiShellProtocol->ReadFile(
101 ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->FileHandle,
102 &Size,
103 &Key->UnicodeChar));
104 }
105
106 /**
107 Function to create a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a
108 SHELL_FILE_HANDLE to support redirecting input from a file.
109
110 @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use.
111 @param[in] HandleLocation The pointer of a location to copy handle with protocol to.
112
113 @retval NULL There was insufficient memory available.
114 @return A pointer to the allocated protocol structure;
115 **/
116 EFI_SIMPLE_TEXT_INPUT_PROTOCOL*
117 EFIAPI
118 CreateSimpleTextInOnFile(
119 IN SHELL_FILE_HANDLE FileHandleToUse,
120 IN EFI_HANDLE *HandleLocation
121 )
122 {
123 SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ProtocolToReturn;
124 EFI_STATUS Status;
125
126 if (HandleLocation == NULL || FileHandleToUse == NULL) {
127 return (NULL);
128 }
129
130 ProtocolToReturn = AllocateZeroPool(sizeof(SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL));
131 if (ProtocolToReturn == NULL) {
132 return (NULL);
133 }
134 ProtocolToReturn->FileHandle = FileHandleToUse;
135 ProtocolToReturn->SimpleTextIn.Reset = FileBasedSimpleTextInReset;
136 ProtocolToReturn->SimpleTextIn.ReadKeyStroke = FileBasedSimpleTextInReadKeyStroke;
137
138 Status = gBS->CreateEvent (
139 EVT_NOTIFY_WAIT,
140 TPL_NOTIFY,
141 ConInWaitForKey,
142 &ProtocolToReturn->SimpleTextIn,
143 &ProtocolToReturn->SimpleTextIn.WaitForKey
144 );
145
146 if (EFI_ERROR(Status)) {
147 FreePool(ProtocolToReturn);
148 return (NULL);
149 }
150 ///@todo possibly also install SimpleTextInputEx on the handle at this point.
151 Status = gBS->InstallProtocolInterface(
152 &(ProtocolToReturn->TheHandle),
153 &gEfiSimpleTextInProtocolGuid,
154 EFI_NATIVE_INTERFACE,
155 &(ProtocolToReturn->SimpleTextIn));
156 if (!EFI_ERROR(Status)) {
157 *HandleLocation = ProtocolToReturn->TheHandle;
158 return ((EFI_SIMPLE_TEXT_INPUT_PROTOCOL*)ProtocolToReturn);
159 } else {
160 FreePool(ProtocolToReturn);
161 return (NULL);
162 }
163 }
164
165 /**
166 Function to close a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a
167 SHELL_FILE_HANDLE to support redirecting input from a file.
168
169 @param[in] SimpleTextIn The pointer to the SimpleTextIn to close.
170
171 @retval EFI_SUCCESS The object was closed.
172 **/
173 EFI_STATUS
174 EFIAPI
175 CloseSimpleTextInOnFile(
176 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn
177 )
178 {
179 EFI_STATUS Status;
180 EFI_STATUS Status1;
181
182 if (SimpleTextIn == NULL) {
183 return (EFI_INVALID_PARAMETER);
184 }
185
186 Status = gBS->CloseEvent(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)SimpleTextIn)->SimpleTextIn.WaitForKey);
187
188 Status1 = gBS->UninstallProtocolInterface(
189 ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL*)SimpleTextIn)->TheHandle,
190 &gEfiSimpleTextInProtocolGuid,
191 &(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL*)SimpleTextIn)->SimpleTextIn));
192
193 FreePool(SimpleTextIn);
194 if (!EFI_ERROR(Status)) {
195 return (Status1);
196 } else {
197 return (Status);
198 }
199 }
200
201 /**
202 Reset the text output device hardware and optionaly run diagnostics.
203
204 @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
205 @param ExtendedVerification Indicates that a more extensive test may be performed
206
207 @retval EFI_SUCCESS The text output device was reset.
208 **/
209 EFI_STATUS
210 EFIAPI
211 FileBasedSimpleTextOutReset (
212 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
213 IN BOOLEAN ExtendedVerification
214 )
215 {
216 return (EFI_SUCCESS);
217 }
218
219 /**
220 Verifies that all characters in a Unicode string can be output to the
221 target device.
222
223 @param[in] This Protocol instance pointer.
224 @param[in] WString The NULL-terminated Unicode string to be examined.
225
226 @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
227 **/
228 EFI_STATUS
229 EFIAPI
230 FileBasedSimpleTextOutTestString (
231 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
232 IN CHAR16 *WString
233 )
234 {
235 return (EFI_SUCCESS);
236 }
237
238 /**
239 Returns information for an available text mode that the output device(s)
240 supports.
241
242 @param[in] This Protocol instance pointer.
243 @param[in] ModeNumber The mode number to return information on.
244 @param[out] Columns Upon return, the number of columns in the selected geometry
245 @param[out] Rows Upon return, the number of rows in the selected geometry
246
247 @retval EFI_UNSUPPORTED The mode number was not valid.
248 **/
249 EFI_STATUS
250 EFIAPI
251 FileBasedSimpleTextOutQueryMode (
252 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
253 IN UINTN ModeNumber,
254 OUT UINTN *Columns,
255 OUT UINTN *Rows
256 )
257 {
258 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *PassThruProtocol = ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)This)->OriginalSimpleTextOut;
259
260 // Pass the QueryMode call thru to the original SimpleTextOutProtocol
261 return (PassThruProtocol->QueryMode(
262 PassThruProtocol,
263 ModeNumber,
264 Columns,
265 Rows));
266 }
267
268 /**
269 Sets the output device(s) to a specified mode.
270
271 @param[in] This Protocol instance pointer.
272 @param[in] ModeNumber The mode number to set.
273
274 @retval EFI_UNSUPPORTED The mode number was not valid.
275 **/
276 EFI_STATUS
277 EFIAPI
278 FileBasedSimpleTextOutSetMode (
279 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
280 IN UINTN ModeNumber
281 )
282 {
283 return (EFI_UNSUPPORTED);
284 }
285
286 /**
287 Sets the background and foreground colors for the OutputString () and
288 ClearScreen () functions.
289
290 @param[in] This Protocol instance pointer.
291 @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
292 bits 4..6 are the background color. All other bits are undefined
293 and must be zero. The valid Attributes are defined in this file.
294
295 @retval EFI_SUCCESS The attribute was set.
296 **/
297 EFI_STATUS
298 EFIAPI
299 FileBasedSimpleTextOutSetAttribute (
300 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
301 IN UINTN Attribute
302 )
303 {
304 return (EFI_SUCCESS);
305 }
306
307 /**
308 Clears the output device(s) display to the currently selected background
309 color.
310
311 @param[in] This Protocol instance pointer.
312
313 @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
314 **/
315 EFI_STATUS
316 EFIAPI
317 FileBasedSimpleTextOutClearScreen (
318 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
319 )
320 {
321 return (EFI_SUCCESS);
322 }
323
324 /**
325 Sets the current coordinates of the cursor position
326
327 @param[in] This Protocol instance pointer.
328 @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
329 @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
330
331 @retval EFI_SUCCESS The operation completed successfully.
332 **/
333 EFI_STATUS
334 EFIAPI
335 FileBasedSimpleTextOutSetCursorPosition (
336 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
337 IN UINTN Column,
338 IN UINTN Row
339 )
340 {
341 return (EFI_SUCCESS);
342 }
343
344 /**
345 Makes the cursor visible or invisible
346
347 @param[in] This Protocol instance pointer.
348 @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
349 set to be invisible.
350
351 @retval EFI_SUCCESS The operation completed successfully.
352 **/
353 EFI_STATUS
354 EFIAPI
355 FileBasedSimpleTextOutEnableCursor (
356 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
357 IN BOOLEAN Visible
358 )
359 {
360 return (EFI_SUCCESS);
361 }
362
363 /**
364 Write a Unicode string to the output device.
365
366 @param[in] This Protocol instance pointer.
367 @param[in] WString The NULL-terminated Unicode string to be displayed on the output
368 device(s). All output devices must also support the Unicode
369 drawing defined in this file.
370 @retval EFI_SUCCESS The string was output to the device.
371 @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
372 the text.
373 @retval EFI_UNSUPPORTED The output device's mode is not currently in a
374 defined text mode.
375 @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
376 characters in the Unicode string could not be
377 rendered and were skipped.
378 **/
379 EFI_STATUS
380 EFIAPI
381 FileBasedSimpleTextOutOutputString (
382 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
383 IN CHAR16 *WString
384 )
385 {
386 UINTN Size;
387 Size = StrLen(WString) * sizeof(CHAR16);
388 return (ShellInfoObject.NewEfiShellProtocol->WriteFile(
389 ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)This)->FileHandle,
390 &Size,
391 WString));
392 }
393
394 /**
395 Function to create a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a
396 SHELL_FILE_HANDLE to support redirecting output from a file.
397
398 @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use.
399 @param[in] HandleLocation The pointer of a location to copy handle with protocol to.
400 @param[in] OriginalProtocol The pointer to the original output protocol for pass thru of functions.
401
402 @retval NULL There was insufficient memory available.
403 @return A pointer to the allocated protocol structure;
404 **/
405 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*
406 EFIAPI
407 CreateSimpleTextOutOnFile(
408 IN SHELL_FILE_HANDLE FileHandleToUse,
409 IN EFI_HANDLE *HandleLocation,
410 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalProtocol
411 )
412 {
413 SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ProtocolToReturn;
414 EFI_STATUS Status;
415
416 if (HandleLocation == NULL || FileHandleToUse == NULL) {
417 return (NULL);
418 }
419
420 ProtocolToReturn = AllocateZeroPool(sizeof(SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL));
421 if (ProtocolToReturn == NULL) {
422 return (NULL);
423 }
424 ProtocolToReturn->FileHandle = FileHandleToUse;
425 ProtocolToReturn->OriginalSimpleTextOut = OriginalProtocol;
426 ProtocolToReturn->SimpleTextOut.Reset = FileBasedSimpleTextOutReset;
427 ProtocolToReturn->SimpleTextOut.TestString = FileBasedSimpleTextOutTestString;
428 ProtocolToReturn->SimpleTextOut.QueryMode = FileBasedSimpleTextOutQueryMode;
429 ProtocolToReturn->SimpleTextOut.SetMode = FileBasedSimpleTextOutSetMode;
430 ProtocolToReturn->SimpleTextOut.SetAttribute = FileBasedSimpleTextOutSetAttribute;
431 ProtocolToReturn->SimpleTextOut.ClearScreen = FileBasedSimpleTextOutClearScreen;
432 ProtocolToReturn->SimpleTextOut.SetCursorPosition = FileBasedSimpleTextOutSetCursorPosition;
433 ProtocolToReturn->SimpleTextOut.EnableCursor = FileBasedSimpleTextOutEnableCursor;
434 ProtocolToReturn->SimpleTextOut.OutputString = FileBasedSimpleTextOutOutputString;
435 ProtocolToReturn->SimpleTextOut.Mode = AllocateZeroPool(sizeof(EFI_SIMPLE_TEXT_OUTPUT_MODE));
436 if (ProtocolToReturn->SimpleTextOut.Mode == NULL) {
437 FreePool(ProtocolToReturn);
438 return (NULL);
439 }
440 ProtocolToReturn->SimpleTextOut.Mode->MaxMode = OriginalProtocol->Mode->MaxMode;
441 ProtocolToReturn->SimpleTextOut.Mode->Mode = OriginalProtocol->Mode->Mode;
442 ProtocolToReturn->SimpleTextOut.Mode->Attribute = OriginalProtocol->Mode->Attribute;
443 ProtocolToReturn->SimpleTextOut.Mode->CursorColumn = OriginalProtocol->Mode->CursorColumn;
444 ProtocolToReturn->SimpleTextOut.Mode->CursorRow = OriginalProtocol->Mode->CursorRow;
445 ProtocolToReturn->SimpleTextOut.Mode->CursorVisible = OriginalProtocol->Mode->CursorVisible;
446
447 Status = gBS->InstallProtocolInterface(
448 &(ProtocolToReturn->TheHandle),
449 &gEfiSimpleTextOutProtocolGuid,
450 EFI_NATIVE_INTERFACE,
451 &(ProtocolToReturn->SimpleTextOut));
452 if (!EFI_ERROR(Status)) {
453 *HandleLocation = ProtocolToReturn->TheHandle;
454 return ((EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*)ProtocolToReturn);
455 } else {
456 FreePool(ProtocolToReturn);
457 return (NULL);
458 }
459 }
460
461 /**
462 Function to close a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a
463 SHELL_FILE_HANDLE to support redirecting output from a file.
464
465 @param[in] SimpleTextOut The pointer to the SimpleTextOUT to close.
466
467 @retval EFI_SUCCESS The object was closed.
468 **/
469 EFI_STATUS
470 EFIAPI
471 CloseSimpleTextOutOnFile(
472 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut
473 )
474 {
475 EFI_STATUS Status;
476 if (SimpleTextOut == NULL) {
477 return (EFI_INVALID_PARAMETER);
478 }
479 Status = gBS->UninstallProtocolInterface(
480 ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*)SimpleTextOut)->TheHandle,
481 &gEfiSimpleTextOutProtocolGuid,
482 &(((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*)SimpleTextOut)->SimpleTextOut));
483 FreePool(SimpleTextOut);
484 return (Status);
485 }