| /** @file | |
| Function definitions for shell simple text in and out on top of file handles. | |
| (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR> | |
| Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "Shell.h" | |
| extern BOOLEAN AsciiRedirection; | |
| typedef struct { | |
| EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn; | |
| SHELL_FILE_HANDLE FileHandle; | |
| EFI_HANDLE TheHandle; | |
| UINT64 RemainingBytesOfInputFile; | |
| } SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL; | |
| typedef struct { | |
| EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOut; | |
| SHELL_FILE_HANDLE FileHandle; | |
| EFI_HANDLE TheHandle; | |
| EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalSimpleTextOut; | |
| } SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; | |
| /** | |
| Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event | |
| Signal the event if there is key available | |
| @param Event Indicates the event that invoke this function. | |
| @param Context Indicates the calling context. | |
| **/ | |
| VOID | |
| EFIAPI | |
| ConInWaitForKey ( | |
| IN EFI_EVENT Event, | |
| IN VOID *Context | |
| ) | |
| { | |
| gBS->SignalEvent (Event); | |
| } | |
| /** | |
| Reset function for the fake simple text input. | |
| @param[in] This A pointer to the SimpleTextIn structure. | |
| @param[in] ExtendedVerification TRUE for extra validation, FALSE otherwise. | |
| @retval EFI_SUCCESS The reset was successful. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextInReset ( | |
| IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, | |
| IN BOOLEAN ExtendedVerification | |
| ) | |
| { | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| ReadKeyStroke function for the fake simple text input. | |
| @param[in] This A pointer to the SimpleTextIn structure. | |
| @param[in, out] Key A pointer to the Key structure to fill. | |
| @retval EFI_SUCCESS The read was successful. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextInReadKeyStroke ( | |
| IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, | |
| IN OUT EFI_INPUT_KEY *Key | |
| ) | |
| { | |
| UINTN Size; | |
| UINTN CharSize; | |
| // | |
| // Verify the parameters | |
| // | |
| if ((Key == NULL) || (This == NULL)) { | |
| return (EFI_INVALID_PARAMETER); | |
| } | |
| // | |
| // Check if we have any characters left in the stream. | |
| // | |
| if (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile == 0) { | |
| return (EFI_NOT_READY); | |
| } | |
| Size = sizeof (CHAR16); | |
| if (!AsciiRedirection) { | |
| CharSize = sizeof (CHAR16); | |
| } else { | |
| CharSize = sizeof (CHAR8); | |
| } | |
| // | |
| // Decrement the amount of free space by Size or set to zero (for odd length files) | |
| // | |
| if (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile > CharSize) { | |
| ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile -= CharSize; | |
| } else { | |
| ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile = 0; | |
| } | |
| Key->ScanCode = 0; | |
| return (ShellInfoObject.NewEfiShellProtocol->ReadFile ( | |
| ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->FileHandle, | |
| &Size, | |
| &Key->UnicodeChar | |
| )); | |
| } | |
| /** | |
| Function to create a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a | |
| SHELL_FILE_HANDLE to support redirecting input from a file. | |
| @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. | |
| @param[in] HandleLocation The pointer of a location to copy handle with protocol to. | |
| @retval NULL There was insufficient memory available. | |
| @return A pointer to the allocated protocol structure; | |
| **/ | |
| EFI_SIMPLE_TEXT_INPUT_PROTOCOL * | |
| CreateSimpleTextInOnFile ( | |
| IN SHELL_FILE_HANDLE FileHandleToUse, | |
| IN EFI_HANDLE *HandleLocation | |
| ) | |
| { | |
| SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ProtocolToReturn; | |
| EFI_STATUS Status; | |
| UINT64 CurrentPosition; | |
| UINT64 FileSize; | |
| if ((HandleLocation == NULL) || (FileHandleToUse == NULL)) { | |
| return (NULL); | |
| } | |
| ProtocolToReturn = AllocateZeroPool (sizeof (SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL)); | |
| if (ProtocolToReturn == NULL) { | |
| return (NULL); | |
| } | |
| ShellGetFileSize (FileHandleToUse, &FileSize); | |
| ShellGetFilePosition (FileHandleToUse, &CurrentPosition); | |
| // | |
| // Initialize the protocol members | |
| // | |
| ProtocolToReturn->RemainingBytesOfInputFile = FileSize - CurrentPosition; | |
| ProtocolToReturn->FileHandle = FileHandleToUse; | |
| ProtocolToReturn->SimpleTextIn.Reset = FileBasedSimpleTextInReset; | |
| ProtocolToReturn->SimpleTextIn.ReadKeyStroke = FileBasedSimpleTextInReadKeyStroke; | |
| Status = gBS->CreateEvent ( | |
| EVT_NOTIFY_WAIT, | |
| TPL_NOTIFY, | |
| ConInWaitForKey, | |
| &ProtocolToReturn->SimpleTextIn, | |
| &ProtocolToReturn->SimpleTextIn.WaitForKey | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| FreePool (ProtocolToReturn); | |
| return (NULL); | |
| } | |
| /// @todo possibly also install SimpleTextInputEx on the handle at this point. | |
| Status = gBS->InstallProtocolInterface ( | |
| &(ProtocolToReturn->TheHandle), | |
| &gEfiSimpleTextInProtocolGuid, | |
| EFI_NATIVE_INTERFACE, | |
| &(ProtocolToReturn->SimpleTextIn) | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| *HandleLocation = ProtocolToReturn->TheHandle; | |
| return ((EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)ProtocolToReturn); | |
| } else { | |
| FreePool (ProtocolToReturn); | |
| return (NULL); | |
| } | |
| } | |
| /** | |
| Function to close a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a | |
| SHELL_FILE_HANDLE to support redirecting input from a file. | |
| @param[in] SimpleTextIn The pointer to the SimpleTextIn to close. | |
| @retval EFI_SUCCESS The object was closed. | |
| **/ | |
| EFI_STATUS | |
| CloseSimpleTextInOnFile ( | |
| IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| EFI_STATUS Status1; | |
| if (SimpleTextIn == NULL) { | |
| return (EFI_INVALID_PARAMETER); | |
| } | |
| Status = gBS->CloseEvent (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)SimpleTextIn)->SimpleTextIn.WaitForKey); | |
| Status1 = gBS->UninstallProtocolInterface ( | |
| ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)SimpleTextIn)->TheHandle, | |
| &gEfiSimpleTextInProtocolGuid, | |
| &(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)SimpleTextIn)->SimpleTextIn) | |
| ); | |
| FreePool (SimpleTextIn); | |
| if (!EFI_ERROR (Status)) { | |
| return (Status1); | |
| } else { | |
| return (Status); | |
| } | |
| } | |
| /** | |
| Reset the text output device hardware and optionally run diagnostics. | |
| @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL | |
| @param ExtendedVerification Indicates that a more extensive test may be performed | |
| @retval EFI_SUCCESS The text output device was reset. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextOutReset ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN BOOLEAN ExtendedVerification | |
| ) | |
| { | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| Verifies that all characters in a Unicode string can be output to the | |
| target device. | |
| @param[in] This Protocol instance pointer. | |
| @param[in] WString The NULL-terminated Unicode string to be examined. | |
| @retval EFI_SUCCESS The device(s) are capable of rendering the output string. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextOutTestString ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN CHAR16 *WString | |
| ) | |
| { | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| Returns information for an available text mode that the output device(s) | |
| supports. | |
| @param[in] This Protocol instance pointer. | |
| @param[in] ModeNumber The mode number to return information on. | |
| @param[out] Columns Upon return, the number of columns in the selected geometry | |
| @param[out] Rows Upon return, the number of rows in the selected geometry | |
| @retval EFI_UNSUPPORTED The mode number was not valid. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextOutQueryMode ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN UINTN ModeNumber, | |
| OUT UINTN *Columns, | |
| OUT UINTN *Rows | |
| ) | |
| { | |
| EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *PassThruProtocol; | |
| PassThruProtocol = ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)This)->OriginalSimpleTextOut; | |
| // Pass the QueryMode call thru to the original SimpleTextOutProtocol | |
| return (PassThruProtocol->QueryMode ( | |
| PassThruProtocol, | |
| ModeNumber, | |
| Columns, | |
| Rows | |
| )); | |
| } | |
| /** | |
| Sets the output device(s) to a specified mode. | |
| @param[in] This Protocol instance pointer. | |
| @param[in] ModeNumber The mode number to set. | |
| @retval EFI_UNSUPPORTED The mode number was not valid. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextOutSetMode ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN UINTN ModeNumber | |
| ) | |
| { | |
| return (EFI_UNSUPPORTED); | |
| } | |
| /** | |
| Sets the background and foreground colors for the OutputString () and | |
| ClearScreen () functions. | |
| @param[in] This Protocol instance pointer. | |
| @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and | |
| bits 4..6 are the background color. All other bits are undefined | |
| and must be zero. The valid Attributes are defined in this file. | |
| @retval EFI_SUCCESS The attribute was set. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextOutSetAttribute ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN UINTN Attribute | |
| ) | |
| { | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| Clears the output device(s) display to the currently selected background | |
| color. | |
| @param[in] This Protocol instance pointer. | |
| @retval EFI_UNSUPPORTED The output device is not in a valid text mode. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextOutClearScreen ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This | |
| ) | |
| { | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| Sets the current coordinates of the cursor position | |
| @param[in] This Protocol instance pointer. | |
| @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode | |
| @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode | |
| @retval EFI_SUCCESS The operation completed successfully. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextOutSetCursorPosition ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN UINTN Column, | |
| IN UINTN Row | |
| ) | |
| { | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| Makes the cursor visible or invisible | |
| @param[in] This Protocol instance pointer. | |
| @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is | |
| set to be invisible. | |
| @retval EFI_SUCCESS The operation completed successfully. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextOutEnableCursor ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN BOOLEAN Visible | |
| ) | |
| { | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| Write a Unicode string to the output device. | |
| @param[in] This Protocol instance pointer. | |
| @param[in] WString The NULL-terminated Unicode string to be displayed on the output | |
| device(s). All output devices must also support the Unicode | |
| drawing defined in this file. | |
| @retval EFI_SUCCESS The string was output to the device. | |
| @retval EFI_DEVICE_ERROR The device reported an error while attempting to output | |
| the text. | |
| @retval EFI_UNSUPPORTED The output device's mode is not currently in a | |
| defined text mode. | |
| @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the | |
| characters in the Unicode string could not be | |
| rendered and were skipped. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| FileBasedSimpleTextOutOutputString ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, | |
| IN CHAR16 *WString | |
| ) | |
| { | |
| UINTN Size; | |
| Size = StrLen (WString) * sizeof (CHAR16); | |
| return (ShellInfoObject.NewEfiShellProtocol->WriteFile ( | |
| ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)This)->FileHandle, | |
| &Size, | |
| WString | |
| )); | |
| } | |
| /** | |
| Function to create a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a | |
| SHELL_FILE_HANDLE to support redirecting output from a file. | |
| @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use. | |
| @param[in] HandleLocation The pointer of a location to copy handle with protocol to. | |
| @param[in] OriginalProtocol The pointer to the original output protocol for pass thru of functions. | |
| @retval NULL There was insufficient memory available. | |
| @return A pointer to the allocated protocol structure; | |
| **/ | |
| EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * | |
| CreateSimpleTextOutOnFile ( | |
| IN SHELL_FILE_HANDLE FileHandleToUse, | |
| IN EFI_HANDLE *HandleLocation, | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalProtocol | |
| ) | |
| { | |
| SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ProtocolToReturn; | |
| EFI_STATUS Status; | |
| if ((HandleLocation == NULL) || (FileHandleToUse == NULL)) { | |
| return (NULL); | |
| } | |
| ProtocolToReturn = AllocateZeroPool (sizeof (SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)); | |
| if (ProtocolToReturn == NULL) { | |
| return (NULL); | |
| } | |
| ProtocolToReturn->FileHandle = FileHandleToUse; | |
| ProtocolToReturn->OriginalSimpleTextOut = OriginalProtocol; | |
| ProtocolToReturn->SimpleTextOut.Reset = FileBasedSimpleTextOutReset; | |
| ProtocolToReturn->SimpleTextOut.TestString = FileBasedSimpleTextOutTestString; | |
| ProtocolToReturn->SimpleTextOut.QueryMode = FileBasedSimpleTextOutQueryMode; | |
| ProtocolToReturn->SimpleTextOut.SetMode = FileBasedSimpleTextOutSetMode; | |
| ProtocolToReturn->SimpleTextOut.SetAttribute = FileBasedSimpleTextOutSetAttribute; | |
| ProtocolToReturn->SimpleTextOut.ClearScreen = FileBasedSimpleTextOutClearScreen; | |
| ProtocolToReturn->SimpleTextOut.SetCursorPosition = FileBasedSimpleTextOutSetCursorPosition; | |
| ProtocolToReturn->SimpleTextOut.EnableCursor = FileBasedSimpleTextOutEnableCursor; | |
| ProtocolToReturn->SimpleTextOut.OutputString = FileBasedSimpleTextOutOutputString; | |
| ProtocolToReturn->SimpleTextOut.Mode = AllocateZeroPool (sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE)); | |
| if (ProtocolToReturn->SimpleTextOut.Mode == NULL) { | |
| FreePool (ProtocolToReturn); | |
| return (NULL); | |
| } | |
| ProtocolToReturn->SimpleTextOut.Mode->MaxMode = OriginalProtocol->Mode->MaxMode; | |
| ProtocolToReturn->SimpleTextOut.Mode->Mode = OriginalProtocol->Mode->Mode; | |
| ProtocolToReturn->SimpleTextOut.Mode->Attribute = OriginalProtocol->Mode->Attribute; | |
| ProtocolToReturn->SimpleTextOut.Mode->CursorColumn = OriginalProtocol->Mode->CursorColumn; | |
| ProtocolToReturn->SimpleTextOut.Mode->CursorRow = OriginalProtocol->Mode->CursorRow; | |
| ProtocolToReturn->SimpleTextOut.Mode->CursorVisible = OriginalProtocol->Mode->CursorVisible; | |
| Status = gBS->InstallProtocolInterface ( | |
| &(ProtocolToReturn->TheHandle), | |
| &gEfiSimpleTextOutProtocolGuid, | |
| EFI_NATIVE_INTERFACE, | |
| &(ProtocolToReturn->SimpleTextOut) | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| *HandleLocation = ProtocolToReturn->TheHandle; | |
| return ((EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)ProtocolToReturn); | |
| } else { | |
| SHELL_FREE_NON_NULL (ProtocolToReturn->SimpleTextOut.Mode); | |
| SHELL_FREE_NON_NULL (ProtocolToReturn); | |
| return (NULL); | |
| } | |
| } | |
| /** | |
| Function to close a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a | |
| SHELL_FILE_HANDLE to support redirecting output from a file. | |
| @param[in] SimpleTextOut The pointer to the SimpleTextOUT to close. | |
| @retval EFI_SUCCESS The object was closed. | |
| **/ | |
| EFI_STATUS | |
| CloseSimpleTextOutOnFile ( | |
| IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (SimpleTextOut == NULL) { | |
| return (EFI_INVALID_PARAMETER); | |
| } | |
| Status = gBS->UninstallProtocolInterface ( | |
| ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)SimpleTextOut)->TheHandle, | |
| &gEfiSimpleTextOutProtocolGuid, | |
| &(((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)SimpleTextOut)->SimpleTextOut) | |
| ); | |
| FreePool (SimpleTextOut->Mode); | |
| FreePool (SimpleTextOut); | |
| return (Status); | |
| } |