summaryrefslogtreecommitdiff
path: root/edk2/ShellPkg/Application
diff options
context:
space:
mode:
authorjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2010-11-16 22:31:47 +0000
committerjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2010-11-16 22:31:47 +0000
commit0248708e9ffa0bb2e408033d4ec9d1705cada91a (patch)
tree0445982726d14b5acfb76856536d8c922aad9c6b /edk2/ShellPkg/Application
parente987c84a0471f1e39663921c48c24a77e4b1cde6 (diff)
fixes for IPF, CTRL-C support, and file redirection.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk@11066 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'edk2/ShellPkg/Application')
-rw-r--r--edk2/ShellPkg/Application/Shell/ConsoleLogger.c9
-rw-r--r--edk2/ShellPkg/Application/Shell/ConsoleWrappers.c477
-rw-r--r--edk2/ShellPkg/Application/Shell/ConsoleWrappers.h81
-rw-r--r--edk2/ShellPkg/Application/Shell/Shell.c26
-rw-r--r--edk2/ShellPkg/Application/Shell/Shell.h4
-rw-r--r--edk2/ShellPkg/Application/Shell/Shell.inf10
-rw-r--r--edk2/ShellPkg/Application/Shell/Shell.unibin3868 -> 4142 bytes
-rw-r--r--edk2/ShellPkg/Application/Shell/ShellEnvVar.c37
-rw-r--r--edk2/ShellPkg/Application/Shell/ShellParametersProtocol.c91
-rw-r--r--edk2/ShellPkg/Application/Shell/ShellParametersProtocol.h35
-rw-r--r--edk2/ShellPkg/Application/Shell/ShellProtocol.c224
-rw-r--r--edk2/ShellPkg/Application/Shell/ShellProtocol.h13
12 files changed, 911 insertions, 96 deletions
diff --git a/edk2/ShellPkg/Application/Shell/ConsoleLogger.c b/edk2/ShellPkg/Application/Shell/ConsoleLogger.c
index 2b84d87ad..4b237bf6e 100644
--- a/edk2/ShellPkg/Application/Shell/ConsoleLogger.c
+++ b/edk2/ShellPkg/Application/Shell/ConsoleLogger.c
@@ -76,10 +76,19 @@ ConsoleLoggerInstall(
Status = ConsoleLoggerResetBuffers(*ConsoleInfo);
if (EFI_ERROR(Status)) {
+ SHELL_FREE_NON_NULL((*ConsoleInfo));
+ *ConsoleInfo = NULL;
return (Status);
}
Status = gBS->InstallProtocolInterface(&gImageHandle, &gEfiSimpleTextOutProtocolGuid, EFI_NATIVE_INTERFACE, (VOID*)&((*ConsoleInfo)->OurConOut));
+ if (EFI_ERROR(Status)) {
+ SHELL_FREE_NON_NULL((*ConsoleInfo)->Buffer);
+ SHELL_FREE_NON_NULL((*ConsoleInfo)->Attributes);
+ SHELL_FREE_NON_NULL((*ConsoleInfo));
+ *ConsoleInfo = NULL;
+ return (Status);
+ }
(*ConsoleInfo)->OldConOut = gST->ConOut;
(*ConsoleInfo)->OldConHandle = gST->ConsoleOutHandle;
diff --git a/edk2/ShellPkg/Application/Shell/ConsoleWrappers.c b/edk2/ShellPkg/Application/Shell/ConsoleWrappers.c
new file mode 100644
index 000000000..61b6a5ee5
--- /dev/null
+++ b/edk2/ShellPkg/Application/Shell/ConsoleWrappers.c
@@ -0,0 +1,477 @@
+/** @file
+ Function definitions for shell simple text in and out on top of file handles.
+
+ Copyright (c) 2010, 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 <ShellBase.h>
+
+#include "ConsoleWrappers.h"
+#include "Shell.h"
+
+typedef struct {
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_HANDLE TheHandle;
+} SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
+
+typedef struct {
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOut;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_HANDLE TheHandle;
+} 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
+ )
+{
+ UINT64 Position;
+ UINT64 Size;
+ //
+ // Someone is waiting on the keystroke event, if there's
+ // a key pending, signal the event
+ //
+ // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+ //
+ ShellInfoObject.NewEfiShellProtocol->GetFilePosition(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Context)->FileHandle, &Position);
+ ShellInfoObject.NewEfiShellProtocol->GetFileSize (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)Context)->FileHandle, &Size );
+ if (Position < Size) {
+ 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[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 EFI_INPUT_KEY *Key
+ )
+{
+ UINTN Size;
+ Size = sizeof(CHAR16);
+ if (Key == NULL || This == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ 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*
+EFIAPI
+CreateSimpleTextInOnFile(
+ IN SHELL_FILE_HANDLE FileHandleToUse,
+ IN EFI_HANDLE *HandleLocation
+ )
+{
+ SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ProtocolToReturn;
+ EFI_STATUS Status;
+
+ if (HandleLocation == NULL || FileHandleToUse == NULL) {
+ return (NULL);
+ }
+
+ ProtocolToReturn = AllocateZeroPool(sizeof(SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL));
+ if (ProtocolToReturn == NULL) {
+ return (NULL);
+ }
+ 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
+EFIAPI
+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 optionaly 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
+ )
+{
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ 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.
+
+ @retval NULL There was insufficient memory available.
+ @return A pointer to the allocated protocol structure;
+**/
+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*
+EFIAPI
+CreateSimpleTextOutOnFile(
+ IN SHELL_FILE_HANDLE FileHandleToUse,
+ IN EFI_HANDLE *HandleLocation
+ )
+{
+ 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->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 = 0;
+ ProtocolToReturn->SimpleTextOut.Mode->Mode = 0;
+ ProtocolToReturn->SimpleTextOut.Mode->Attribute = 0;
+ ProtocolToReturn->SimpleTextOut.Mode->CursorColumn = 0;
+ ProtocolToReturn->SimpleTextOut.Mode->CursorRow = 0;
+ ProtocolToReturn->SimpleTextOut.Mode->CursorVisible = FALSE;
+
+ 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 {
+ FreePool(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
+EFIAPI
+CloseSimpleTextOutOnFile(
+ OUT 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);
+ return (Status);
+}
diff --git a/edk2/ShellPkg/Application/Shell/ConsoleWrappers.h b/edk2/ShellPkg/Application/Shell/ConsoleWrappers.h
new file mode 100644
index 000000000..966a9225f
--- /dev/null
+++ b/edk2/ShellPkg/Application/Shell/ConsoleWrappers.h
@@ -0,0 +1,81 @@
+/** @file
+ Function definitions for shell simple text in and out on top of file handles.
+
+ Copyright (c) 2010, 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.
+
+**/
+
+#ifndef _SHELL_CONSOLE_WRAPPERS_HEADER_
+#define _SHELL_CONSOLE_WRAPPERS_HEADER_
+
+/**
+ 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*
+EFIAPI
+CreateSimpleTextInOnFile(
+ IN SHELL_FILE_HANDLE FileHandleToUse,
+ IN EFI_HANDLE *HandleLocation
+ );
+
+/**
+ 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
+EFIAPI
+CloseSimpleTextInOnFile(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn
+ );
+
+/**
+ 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.
+
+ @retval NULL There was insufficient memory available.
+ @return A pointer to the allocated protocol structure;
+**/
+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*
+EFIAPI
+CreateSimpleTextOutOnFile(
+ IN SHELL_FILE_HANDLE FileHandleToUse,
+ IN EFI_HANDLE *HandleLocation
+ );
+
+/**
+ 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
+EFIAPI
+CloseSimpleTextOutOnFile(
+ OUT EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut
+ );
+
+#endif //_SHELL_CONSOLE_WRAPPERS_HEADER_
+
diff --git a/edk2/ShellPkg/Application/Shell/Shell.c b/edk2/ShellPkg/Application/Shell/Shell.c
index ddd5d1712..b626ec2ac 100644
--- a/edk2/ShellPkg/Application/Shell/Shell.c
+++ b/edk2/ShellPkg/Application/Shell/Shell.c
@@ -52,6 +52,10 @@ SHELL_INFO ShellInfoObject = {
NULL,
{0,0,NULL,NULL},
{0,0},
+ NULL,
+ NULL,
+ NULL,
+ NULL
};
STATIC CONST CHAR16 mScriptExtension[] = L".NSH";
@@ -271,9 +275,7 @@ UefiMain (
//
// Set up the event for CTRL-C monitoring...
//
-
- ///@todo add support for using SimpleInputEx here
- // if SimpleInputEx is not available display a warning.
+ Status = InernalEfiShellStartMonitor();
}
if (!EFI_ERROR(Status) && PcdGet8(PcdShellSupportLevel) >= 1) {
@@ -304,6 +306,11 @@ UefiMain (
ShellInfoObject.ConsoleInfo->RowCounter = 0;
//
+ // Reset the CTRL-C event (yes we ignore the return values)
+ //
+ Status = gBS->CheckEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);
+
+ //
// Display Prompt
//
Status = DoShellPrompt();
@@ -319,11 +326,6 @@ UefiMain (
gBS->CloseEvent(ShellInfoObject.UserBreakTimer);
DEBUG_CODE(ShellInfoObject.UserBreakTimer = NULL;);
}
-
- if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){
- ShellInfoObject.NewEfiShellProtocol->SetEnv(L"cwd", L"", TRUE);
- }
-
if (ShellInfoObject.ImageDevPath != NULL) {
FreePool(ShellInfoObject.ImageDevPath);
DEBUG_CODE(ShellInfoObject.ImageDevPath = NULL;);
@@ -337,6 +339,9 @@ UefiMain (
DEBUG_CODE(ShellInfoObject.NewShellParametersProtocol = NULL;);
}
if (ShellInfoObject.NewEfiShellProtocol != NULL){
+ if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){
+ ShellInfoObject.NewEfiShellProtocol->SetEnv(L"cwd", L"", TRUE);
+ }
CleanUpShellProtocol(ShellInfoObject.NewEfiShellProtocol);
DEBUG_CODE(ShellInfoObject.NewEfiShellProtocol = NULL;);
}
@@ -1186,6 +1191,7 @@ RunCommand(
SHELL_FILE_HANDLE OriginalStdIn;
SHELL_FILE_HANDLE OriginalStdOut;
SHELL_FILE_HANDLE OriginalStdErr;
+ SYSTEM_TABLE_INFO OriginalSystemTableInfo;
CHAR16 *TempLocation3;
UINTN Count;
UINTN Count2;
@@ -1311,7 +1317,7 @@ RunCommand(
- Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr);
+ Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);
if (EFI_ERROR(Status)) {
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);
} else {
@@ -1430,7 +1436,7 @@ RunCommand(
RestoreArgcArgv(ShellInfoObject.NewShellParametersProtocol, &Argv, &Argc);
- RestoreStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr);
+ RestoreStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);
}
if (CommandName != NULL) {
if (ShellCommandGetCurrentScriptFile() != NULL && !IsScriptOnlyCommand(CommandName)) {
diff --git a/edk2/ShellPkg/Application/Shell/Shell.h b/edk2/ShellPkg/Application/Shell/Shell.h
index 6f165e551..ec32355b6 100644
--- a/edk2/ShellPkg/Application/Shell/Shell.h
+++ b/edk2/ShellPkg/Application/Shell/Shell.h
@@ -105,6 +105,10 @@ typedef struct {
EFI_SHELL_PARAMETERS_PROTOCOL *OldShellParameters; ///< old shell parameters to reinstall upon exiting.
SHELL_PROTOCOL_HANDLE_LIST OldShellList; ///< List of other instances to reinstall when closing.
SPLIT_LIST SplitList; ///< List of Splits in FILO stack.
+ EFI_HANDLE CtrlCNotifyHandle1; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ EFI_HANDLE CtrlCNotifyHandle2; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ EFI_HANDLE CtrlCNotifyHandle3; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ EFI_HANDLE CtrlCNotifyHandle4; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
} SHELL_INFO;
extern SHELL_INFO ShellInfoObject;
diff --git a/edk2/ShellPkg/Application/Shell/Shell.inf b/edk2/ShellPkg/Application/Shell/Shell.inf
index e2649a725..e690e2e7f 100644
--- a/edk2/ShellPkg/Application/Shell/Shell.inf
+++ b/edk2/ShellPkg/Application/Shell/Shell.inf
@@ -44,6 +44,8 @@
Shell.uni
ConsoleLogger.c
ConsoleLogger.h
+ ConsoleWrappers.c
+ ConsoleWrappers.h
[Packages]
MdePkg/MdePkg.dec
@@ -75,12 +77,16 @@
[Protocols]
gEfiShellProtocolGuid # ALWAYS_PRODUCED
+ # SOMETIMES_CONSUMED
gEfiShellParametersProtocolGuid # ALWAYS_PRODUCED
- gEfiShellEnvironment2Guid # SOMETIMES_PRODUCED
- gEfiShellInterfaceGuid # SOMETIMES_PRODUCED
+ # SOMETIMES_CONSUMED
+
+# gEfiShellEnvironment2Guid # SOMETIMES_PRODUCED
+# gEfiShellInterfaceGuid # SOMETIMES_PRODUCED
gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED
gEfiSimpleTextInputExProtocolGuid # ALWAYS_CONSUMED
+ gEfiSimpleTextInProtocolGuid # ALWAYS_CONSUMED
gEfiSimpleTextOutProtocolGuid # ALWAYS_CONSUMED
gEfiSimpleFileSystemProtocolGuid # ALWAYS_CONSUMED
gEfiLoadedImageProtocolGuid # ALWAYS_CONSUMED
diff --git a/edk2/ShellPkg/Application/Shell/Shell.uni b/edk2/ShellPkg/Application/Shell/Shell.uni
index 82a87aeb3..e7327f3db 100644
--- a/edk2/ShellPkg/Application/Shell/Shell.uni
+++ b/edk2/ShellPkg/Application/Shell/Shell.uni
Binary files differ
diff --git a/edk2/ShellPkg/Application/Shell/ShellEnvVar.c b/edk2/ShellPkg/Application/Shell/ShellEnvVar.c
index cd55fa907..f22fb705d 100644
--- a/edk2/ShellPkg/Application/Shell/ShellEnvVar.c
+++ b/edk2/ShellPkg/Application/Shell/ShellEnvVar.c
@@ -13,6 +13,7 @@
**/
#include <Uefi.h>
+#include <ShellBase.h>
#include <Guid/ShellVariableGuid.h>
@@ -24,7 +25,6 @@
#include "ShellEnvVar.h"
-
/**
Reports whether an environment variable is Volatile or Non-Volatile.
@@ -169,18 +169,31 @@ GetEnvironmentVariableList(
}
if (!EFI_ERROR(Status) && CompareGuid(&Guid, &gShellVariableGuid)){
VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));
- ValSize = 0;
- Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
- if (Status == EFI_BUFFER_TOO_SMALL){
- VarList->Val = AllocatePool(ValSize);
- ASSERT(VarList->Val != NULL);
+ if (VarList == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ ValSize = 0;
Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
- }
- if (!EFI_ERROR(Status)) {
- VarList->Key = AllocatePool(StrSize(VariableName));
- ASSERT(VarList->Key != NULL);
- StrCpy(VarList->Key, VariableName);
- InsertTailList(ListHead, &VarList->Link);
+ if (Status == EFI_BUFFER_TOO_SMALL){
+ VarList->Val = AllocatePool(ValSize);
+ if (VarList->Val == NULL) {
+ SHELL_FREE_NON_NULL(VarList);
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
+ }
+ }
+ if (!EFI_ERROR(Status)) {
+ VarList->Key = AllocatePool(StrSize(VariableName));
+ if (VarList->Key == NULL) {
+ SHELL_FREE_NON_NULL(VarList->Val);
+ SHELL_FREE_NON_NULL(VarList);
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ StrCpy(VarList->Key, VariableName);
+ InsertTailList(ListHead, &VarList->Link);
+ }
+ }
}
} // compare guid
} // while
diff --git a/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.c b/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.c
index 5e3e48b41..b594d3434 100644
--- a/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.c
+++ b/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.c
@@ -14,6 +14,7 @@
**/
#include "ShellParametersProtocol.h"
+#include "ConsoleWrappers.h"
/**
return the next parameter from a command line string;
@@ -423,13 +424,14 @@ CleanUpShellParametersProtocol (
structure by parsing NewCommandLine. The current values are returned to the
user.
- If OldStdIn or OldStdOut is NULL then that value is not returned.
+ This will also update the system table.
@param[in,out] ShellParameters Pointer to parameter structure to modify.
@param[in] NewCommandLine The new command line to parse and use.
@param[out] OldStdIn Pointer to old StdIn.
@param[out] OldStdOut Pointer to old StdOut.
@param[out] OldStdErr Pointer to old StdErr.
+ @param[out] SystemTableInfo Pointer to old system table information.
@retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
@@ -441,7 +443,8 @@ UpdateStdInStdOutStdErr(
IN CONST CHAR16 *NewCommandLine,
OUT SHELL_FILE_HANDLE *OldStdIn,
OUT SHELL_FILE_HANDLE *OldStdOut,
- OUT SHELL_FILE_HANDLE *OldStdErr
+ OUT SHELL_FILE_HANDLE *OldStdErr,
+ OUT SYSTEM_TABLE_INFO *SystemTableInfo
)
{
CHAR16 *CommandLineCopy;
@@ -464,7 +467,6 @@ UpdateStdInStdOutStdErr(
CHAR16 TagBuffer[2];
SPLIT_LIST *Split;
- ASSERT(ShellParameters != NULL);
OutUnicode = TRUE;
InUnicode = TRUE;
ErrUnicode = TRUE;
@@ -478,16 +480,20 @@ UpdateStdInStdOutStdErr(
OutAppend = FALSE;
CommandLineCopy = NULL;
- if (OldStdIn != NULL) {
- *OldStdIn = ShellParameters->StdIn;
- }
- if (OldStdOut != NULL) {
- *OldStdOut = ShellParameters->StdOut;
- }
- if (OldStdErr != NULL) {
- *OldStdErr = ShellParameters->StdErr;
+ if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {
+ return (EFI_INVALID_PARAMETER);
}
+ SystemTableInfo->ConIn = gST->ConIn;
+ SystemTableInfo->ConInHandle = gST->ConsoleInHandle;
+ SystemTableInfo->ConOut = gST->ConOut;
+ SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;
+ SystemTableInfo->ConErr = gST->StdErr;
+ SystemTableInfo->ConErrHandle = gST->StandardErrorHandle;
+ *OldStdIn = ShellParameters->StdIn;
+ *OldStdOut = ShellParameters->StdOut;
+ *OldStdErr = ShellParameters->StdErr;
+
if (NewCommandLine == NULL) {
return (EFI_SUCCESS);
}
@@ -726,6 +732,7 @@ UpdateStdInStdOutStdErr(
}
if (!EFI_ERROR(Status)) {
ShellParameters->StdErr = TempHandle;
+ gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);
}
}
@@ -766,6 +773,7 @@ UpdateStdInStdOutStdErr(
}
if (!EFI_ERROR(Status)) {
ShellParameters->StdOut = TempHandle;
+ gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);
}
}
}
@@ -787,6 +795,7 @@ UpdateStdInStdOutStdErr(
ASSERT(TempHandle != NULL);
}
ShellParameters->StdOut = TempHandle;
+ gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);
}
//
@@ -806,6 +815,7 @@ UpdateStdInStdOutStdErr(
ASSERT(TempHandle != NULL);
}
ShellParameters->StdErr = TempHandle;
+ gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);
}
//
@@ -822,6 +832,7 @@ UpdateStdInStdOutStdErr(
Status = EFI_INVALID_PARAMETER;
} else {
ShellParameters->StdIn = TempHandle;
+ gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);
}
}
@@ -839,11 +850,16 @@ UpdateStdInStdOutStdErr(
}
if (!EFI_ERROR(Status)) {
ShellParameters->StdIn = TempHandle;
+ gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);
}
}
}
}
FreePool(CommandLineCopy);
+
+ if (gST->ConIn == NULL ||gST->ConOut == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
return (Status);
}
@@ -851,38 +867,69 @@ UpdateStdInStdOutStdErr(
Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
structure with StdIn and StdOut. The current values are de-allocated.
- @param[in,out] ShellParameters pointer to parameter structure to modify
- @param[out] OldStdIn Pointer to old StdIn.
- @param[out] OldStdOut Pointer to old StdOut.
- @param[out] OldStdErr Pointer to old StdErr.
+ @param[in,out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] OldStdIn Pointer to old StdIn.
+ @param[in] OldStdOut Pointer to old StdOut.
+ @param[in] OldStdErr Pointer to old StdErr.
+ @param[in] SystemTableInfo Pointer to old system table information.
**/
EFI_STATUS
EFIAPI
RestoreStdInStdOutStdErr (
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
- OUT SHELL_FILE_HANDLE *OldStdIn OPTIONAL,
- OUT SHELL_FILE_HANDLE *OldStdOut OPTIONAL,
- OUT SHELL_FILE_HANDLE *OldStdErr OPTIONAL
+ IN SHELL_FILE_HANDLE *OldStdIn,
+ IN SHELL_FILE_HANDLE *OldStdOut,
+ IN SHELL_FILE_HANDLE *OldStdErr,
+ IN SYSTEM_TABLE_INFO *SystemTableInfo
)
{
SPLIT_LIST *Split;
+
+ if (ShellParameters == NULL
+ ||OldStdIn == NULL
+ ||OldStdOut == NULL
+ ||OldStdErr == NULL
+ ||SystemTableInfo == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
} else {
Split = NULL;
}
- if (OldStdIn != NULL && ShellParameters->StdIn != *OldStdIn) {
+ if (ShellParameters->StdIn != *OldStdIn) {
if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {
gEfiShellProtocol->CloseFile(ShellParameters->StdIn);
}
- ShellParameters->StdIn = OldStdIn==NULL?NULL:*OldStdIn;
+ ShellParameters->StdIn = *OldStdIn;
}
- if (OldStdOut != NULL && ShellParameters->StdOut != *OldStdOut) {
+ if (ShellParameters->StdOut != *OldStdOut) {
if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {
gEfiShellProtocol->CloseFile(ShellParameters->StdOut);
}
- ShellParameters->StdOut = OldStdOut==NULL?NULL:*OldStdOut;
+ ShellParameters->StdOut = *OldStdOut;
+ }
+ if (ShellParameters->StdErr != *OldStdErr) {
+ gEfiShellProtocol->CloseFile(ShellParameters->StdErr);
+ ShellParameters->StdErr = *OldStdErr;
+ }
+
+ if (gST->ConIn != SystemTableInfo->ConIn) {
+ CloseSimpleTextInOnFile(gST->ConIn);
+ gST->ConIn = SystemTableInfo->ConIn;
+ gST->ConsoleInHandle = SystemTableInfo->ConInHandle;
+ }
+ if (gST->ConOut != SystemTableInfo->ConOut) {
+ CloseSimpleTextOutOnFile(gST->ConOut);
+ gST->ConOut = SystemTableInfo->ConOut;
+ gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;
}
+ if (gST->StdErr != SystemTableInfo->ConErr) {
+ CloseSimpleTextOutOnFile(gST->StdErr);
+ gST->StdErr = SystemTableInfo->ConErr;
+ gST->StandardErrorHandle = SystemTableInfo->ConErrHandle;
+ }
+
return (EFI_SUCCESS);
}
/**
diff --git a/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.h b/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.h
index 3a5fc30bc..2d1958761 100644
--- a/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.h
+++ b/edk2/ShellPkg/Application/Shell/ShellParametersProtocol.h
@@ -21,6 +21,8 @@
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/EfiShellParameters.h>
#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleTextIn.h>
#include <Guid/ShellVariableGuid.h>
@@ -116,6 +118,15 @@ RestoreArgcArgv(
IN UINTN *OldArgc
);
+typedef struct {
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
+ EFI_HANDLE ConInHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+ EFI_HANDLE ConOutHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConErr;
+ EFI_HANDLE ConErrHandle;
+} SYSTEM_TABLE_INFO;
+
/**
Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
structure by parsing NewCommandLine. The current values are returned to the
@@ -128,6 +139,7 @@ RestoreArgcArgv(
@param[out] OldStdIn Pointer to old StdIn.
@param[out] OldStdOut Pointer to old StdOut.
@param[out] OldStdErr Pointer to old StdErr.
+ @param[out] SystemTableInfo Pointer to old system table information.
@retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
@@ -137,27 +149,30 @@ EFIAPI
UpdateStdInStdOutStdErr(
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
IN CONST CHAR16 *NewCommandLine,
- OUT SHELL_FILE_HANDLE *OldStdIn OPTIONAL,
- OUT SHELL_FILE_HANDLE *OldStdOut OPTIONAL,
- OUT SHELL_FILE_HANDLE *OldStdErr OPTIONAL
+ OUT SHELL_FILE_HANDLE *OldStdIn,
+ OUT SHELL_FILE_HANDLE *OldStdOut,
+ OUT SHELL_FILE_HANDLE *OldStdErr,
+ OUT SYSTEM_TABLE_INFO *SystemTableInfo
);
/**
Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
structure with StdIn and StdOut. The current values are de-allocated.
- @param[in,out] ShellParameters pointer to parameter structure to modify
- @param[out] OldStdIn Pointer to old StdIn.
- @param[out] OldStdOut Pointer to old StdOut.
- @param[out] OldStdErr Pointer to old StdErr.
+ @param[in,out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] OldStdIn Pointer to old StdIn.
+ @param[in] OldStdOut Pointer to old StdOut.
+ @param[in] OldStdErr Pointer to old StdErr.
+ @param[in] SystemTableInfo Pointer to old system table information.
**/
EFI_STATUS
EFIAPI
RestoreStdInStdOutStdErr (
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
- OUT SHELL_FILE_HANDLE *OldStdIn OPTIONAL,
- OUT SHELL_FILE_HANDLE *OldStdOut OPTIONAL,
- OUT SHELL_FILE_HANDLE *OldStdErr OPTIONAL
+ IN SHELL_FILE_HANDLE *OldStdIn,
+ IN SHELL_FILE_HANDLE *OldStdOut,
+ IN SHELL_FILE_HANDLE *OldStdErr,
+ IN SYSTEM_TABLE_INFO *SystemTableInfo
);
/**
diff --git a/edk2/ShellPkg/Application/Shell/ShellProtocol.c b/edk2/ShellPkg/Application/Shell/ShellProtocol.c
index eaec87971..392298989 100644
--- a/edk2/ShellPkg/Application/Shell/ShellProtocol.c
+++ b/edk2/ShellPkg/Application/Shell/ShellProtocol.c
@@ -34,7 +34,7 @@ EfiShellClose (
)
{
ShellFileHandleRemove(FileHandle);
- return (FileHandleClose(FileHandle));
+ return (FileHandleClose(ConvertShellHandleToEfiFileProtocol(FileHandle)));
}
/**
@@ -475,8 +475,12 @@ EfiShellGetDevicePathFromFilePath(
EFI_HANDLE Handle;
EFI_STATUS Status;
+ if (Path == NULL) {
+ return (NULL);
+ }
+
MapName = NULL;
- ASSERT(Path != NULL);
+ NewPath = NULL;
if (StrStr(Path, L":") == NULL) {
Cwd = EfiShellGetCurDir(NULL);
@@ -488,7 +492,7 @@ EfiShellGetDevicePathFromFilePath(
NewPath = AllocateZeroPool(Size);
ASSERT(NewPath != NULL);
StrCpy(NewPath, Cwd);
- if ((NewPath[0] == (CHAR16)L'\\') &&
+ if ((Path[0] == (CHAR16)L'\\') &&
(NewPath[StrLen(NewPath)-1] == (CHAR16)L'\\')
) {
((CHAR16*)NewPath)[StrLen(NewPath)-1] = CHAR_NULL;
@@ -803,6 +807,7 @@ EfiShellOpenRootByHandle(
could not be opened.
@retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.
@retval EFI_DEVICE_ERROR The device had an error
+ @retval EFI_INVALID_PARAMETER FileHandle is NULL.
**/
EFI_STATUS
EFIAPI
@@ -814,6 +819,10 @@ EfiShellOpenRoot(
EFI_STATUS Status;
EFI_HANDLE Handle;
+ if (FileHandle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
//
// find the handle of the device with that device handle and the file system
//
@@ -876,11 +885,19 @@ InternalOpenFileDevicePath(
EFI_FILE_PROTOCOL *Handle1;
EFI_FILE_PROTOCOL *Handle2;
EFI_DEVICE_PATH_PROTOCOL *DpCopy;
+ FILEPATH_DEVICE_PATH *AlignedNode;
- ASSERT(FileHandle != NULL);
- *FileHandle = NULL;
- Handle1 = NULL;
- DpCopy = DevicePath;
+ if (FileHandle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *FileHandle = NULL;
+ Handle1 = NULL;
+ Handle2 = NULL;
+ Handle = NULL;
+ DpCopy = DevicePath;
+ ShellHandle = NULL;
+ FilePathNode = NULL;
+ AlignedNode = NULL;
Status = EfiShellOpenRoot(DevicePath, &ShellHandle);
@@ -903,6 +920,8 @@ InternalOpenFileDevicePath(
; !IsDevicePathEnd (&FilePathNode->Header)
; FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header)
){
+ SHELL_FREE_NON_NULL(AlignedNode);
+ AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePathNode), FilePathNode);
//
// For file system access each node should be a file path component
//
@@ -926,7 +945,7 @@ InternalOpenFileDevicePath(
Status = Handle2->Open (
Handle2,
&Handle1,
- FilePathNode->PathName,
+ AlignedNode->PathName,
OpenMode,
Attributes
);
@@ -944,7 +963,7 @@ InternalOpenFileDevicePath(
Status = Handle2->Open (
Handle2,
&Handle1,
- FilePathNode->PathName,
+ AlignedNode->PathName,
OpenMode &~EFI_FILE_MODE_CREATE,
Attributes
);
@@ -956,7 +975,7 @@ InternalOpenFileDevicePath(
Status = Handle2->Open (
Handle2,
&Handle1,
- FilePathNode->PathName,
+ AlignedNode->PathName,
OpenMode,
Attributes
);
@@ -965,7 +984,7 @@ InternalOpenFileDevicePath(
//
// Close the last node
//
- Handle2->Close (Handle2);
+ ShellInfoObject.NewEfiShellProtocol->CloseFile (Handle2);
//
// If there's been an error, stop
@@ -976,9 +995,10 @@ InternalOpenFileDevicePath(
} // for loop
}
}
+ SHELL_FREE_NON_NULL(AlignedNode);
if (EFI_ERROR(Status)) {
if (Handle1 != NULL) {
- Handle1->Close(Handle1);
+ ShellInfoObject.NewEfiShellProtocol->CloseFile(Handle1);
}
} else {
*FileHandle = ConvertEfiFileProtocolToShellHandle(Handle1, ShellFileHandleGetPath(ShellHandle));
@@ -1867,11 +1887,6 @@ UpdateFileName(
If FileHandle is a file and matches all of the remaining Pattern (which would be
on its last node), then add a EFI_SHELL_FILE_INFO object for this file to fileList.
- if FileList is NULL, then ASSERT
- if FilePattern is NULL, then ASSERT
- if UnicodeCollation is NULL, then ASSERT
- if FileHandle is NULL, then ASSERT
-
Upon a EFI_SUCCESS return fromt he function any the caller is responsible to call
FreeFileList with FileList.
@@ -1880,6 +1895,7 @@ UpdateFileName(
@param[in] FileHandle The FileHandle to start with
@param[in,out] FileList pointer to pointer to list of found files.
@param[in] ParentNode The node for the parent. Same file as identified by HANDLE.
+ @param[in] MapName The file system name this file is on.
@retval EFI_SUCCESS all files were found and the FileList contains a list.
@retval EFI_NOT_FOUND no files were found
@@ -1892,7 +1908,8 @@ ShellSearchHandle(
IN EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation,
IN SHELL_FILE_HANDLE FileHandle,
IN OUT EFI_SHELL_FILE_INFO **FileList,
- IN CONST EFI_SHELL_FILE_INFO *ParentNode OPTIONAL
+ IN CONST EFI_SHELL_FILE_INFO *ParentNode OPTIONAL,
+ IN CONST CHAR16 *MapName
)
{
EFI_STATUS Status;
@@ -1902,6 +1919,8 @@ ShellSearchHandle(
EFI_SHELL_FILE_INFO *ShellInfoNode;
EFI_SHELL_FILE_INFO *NewShellNode;
BOOLEAN Directory;
+ CHAR16 *NewFullName;
+ UINTN Size;
if ( FilePattern == NULL
|| UnicodeCollation == NULL
@@ -1965,7 +1984,20 @@ ShellSearchHandle(
; ShellInfoNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ShellInfo->Link, &ShellInfoNode->Link)
){
if (UnicodeCollation->MetaiMatch(UnicodeCollation, (CHAR16*)ShellInfoNode->FileName, CurrentFilePattern)){
- if (Directory){
+ if (ShellInfoNode->FullName != NULL && StrStr(ShellInfoNode->FullName, L":") == NULL) {
+ Size = StrSize(ShellInfoNode->FullName);
+ Size += StrSize(MapName) + sizeof(CHAR16);
+ NewFullName = AllocateZeroPool(Size);
+ if (NewFullName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ StrCpy(NewFullName, MapName);
+ StrCat(NewFullName, ShellInfoNode->FullName+1);
+ FreePool((VOID*)ShellInfoNode->FullName);
+ ShellInfoNode->FullName = NewFullName;
+ }
+ }
+ if (Directory && !EFI_ERROR(Status)){
//
// should be a directory
//
@@ -1991,9 +2023,9 @@ ShellSearchHandle(
//
// recurse with the next part of the pattern
//
- Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode);
+ Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode, MapName);
}
- } else {
+ } else if (!EFI_ERROR(Status)) {
//
// should be a file
//
@@ -2109,18 +2141,14 @@ EfiShellFindFiles(
; *PatternCurrentLocation != ':'
; PatternCurrentLocation++);
PatternCurrentLocation++;
- Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL);
+ Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL, MapName);
}
FreePool(RootDevicePath);
}
}
- if (PatternCopy != NULL) {
- FreePool(PatternCopy);
- }
- if (MapName != NULL) {
- FreePool(MapName);
- }
+ SHELL_FREE_NON_NULL(PatternCopy);
+ SHELL_FREE_NON_NULL(MapName);
return(Status);
}
@@ -2996,23 +3024,26 @@ CreatePopulateInstallShellProtocol (
UINTN HandleCounter;
SHELL_PROTOCOL_HANDLE_LIST *OldProtocolNode;
+ if (NewShell == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
BufferSize = 0;
Buffer = NULL;
OldProtocolNode = NULL;
InitializeListHead(&ShellInfoObject.OldShellList.Link);
- ASSERT(NewShell != NULL);
-
//
// Initialize EfiShellProtocol object...
//
- *NewShell = &mShellProtocol;
Status = gBS->CreateEvent(0,
0,
NULL,
NULL,
&mShellProtocol.ExecutionBreak);
- ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
//
// Get the size of the buffer we need.
@@ -3027,13 +3058,18 @@ CreatePopulateInstallShellProtocol (
// Allocate and recall with buffer of correct size
//
Buffer = AllocateZeroPool(BufferSize);
- ASSERT(Buffer != NULL);
+ if (Buffer == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
Status = gBS->LocateHandle(ByProtocol,
&gEfiShellProtocolGuid,
NULL,
&BufferSize,
Buffer);
- ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ FreePool(Buffer);
+ return (Status);
+ }
//
// now overwrite each of them, but save the info to restore when we end.
//
@@ -3056,7 +3092,7 @@ CreatePopulateInstallShellProtocol (
OldProtocolNode->Handle,
&gEfiShellProtocolGuid,
OldProtocolNode->Interface,
- (VOID*)(*NewShell));
+ (VOID*)(&mShellProtocol));
if (!EFI_ERROR(Status)) {
//
// we reinstalled sucessfully. log this so we can reverse it later.
@@ -3079,7 +3115,7 @@ CreatePopulateInstallShellProtocol (
&gImageHandle,
&gEfiShellProtocolGuid,
EFI_NATIVE_INTERFACE,
- (VOID*)(*NewShell));
+ (VOID*)(&mShellProtocol));
}
if (PcdGetBool(PcdShellSupportOldProtocols)){
@@ -3087,6 +3123,9 @@ CreatePopulateInstallShellProtocol (
///@todo do we need to support ShellEnvironment (not ShellEnvironment2) also?
}
+ if (!EFI_ERROR(Status)) {
+ *NewShell = &mShellProtocol;
+ }
return (Status);
}
@@ -3106,8 +3145,9 @@ CleanUpShellProtocol (
IN OUT EFI_SHELL_PROTOCOL *NewShell
)
{
- EFI_STATUS Status;
- SHELL_PROTOCOL_HANDLE_LIST *Node2;
+ EFI_STATUS Status;
+ SHELL_PROTOCOL_HANDLE_LIST *Node2;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
//
// if we need to restore old protocols...
@@ -3122,7 +3162,6 @@ CleanUpShellProtocol (
&gEfiShellProtocolGuid,
NewShell,
Node2->Interface);
- ASSERT_EFI_ERROR(Status);
FreePool(Node2);
}
} else {
@@ -3132,11 +3171,116 @@ CleanUpShellProtocol (
Status = gBS->UninstallProtocolInterface(gImageHandle,
&gEfiShellProtocolGuid,
NewShell);
- ASSERT_EFI_ERROR(Status);
}
Status = gBS->CloseEvent(NewShell->ExecutionBreak);
+ NewShell->ExecutionBreak = NULL;
+
+ Status = gBS->OpenProtocol(
+ gST->ConsoleInHandle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID**)&SimpleEx,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle1);
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle2);
return (Status);
}
+/**
+ Notification function for keystrokes.
+
+ @param[in] KeyData The key that was pressed.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+NotificationFunction(
+ IN EFI_KEY_DATA *KeyData
+ )
+{
+ if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {
+ return (EFI_UNSUPPORTED);
+ }
+ return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak));
+}
+
+/**
+ Function to start monitoring for CTRL-C using SimpleTextInputEx. This
+ feature's enabled state was not known when the shell initially launched.
+
+ @retval EFI_SUCCESS The feature is enabled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
+**/
+EFI_STATUS
+EFIAPI
+InernalEfiShellStartMonitor(
+ VOID
+ )
+{
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
+ EFI_KEY_DATA KeyData;
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol(
+ gST->ConsoleInHandle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID**)&SimpleEx,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SHELL_NO_IN_EX),
+ ShellInfoObject.HiiHandle);
+ return (EFI_SUCCESS);
+ }
+ if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ KeyData.KeyState.KeyToggleState = 0;
+ KeyData.Key.ScanCode = 0;
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
+ KeyData.Key.UnicodeChar = L'c';
+
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlCNotifyHandle1);
+
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
+ if (!EFI_ERROR(Status)) {
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlCNotifyHandle2);
+ }
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
+ KeyData.Key.UnicodeChar = 3;
+ if (!EFI_ERROR(Status)) {
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlCNotifyHandle3);
+ }
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
+ if (!EFI_ERROR(Status)) {
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlCNotifyHandle4);
+ }
+ return (Status);
+}
diff --git a/edk2/ShellPkg/Application/Shell/ShellProtocol.h b/edk2/ShellPkg/Application/Shell/ShellProtocol.h
index d03a382f6..38e71b40d 100644
--- a/edk2/ShellPkg/Application/Shell/ShellProtocol.h
+++ b/edk2/ShellPkg/Application/Shell/ShellProtocol.h
@@ -31,6 +31,7 @@
#include <Protocol/LoadedImage.h>
#include <Protocol/UnicodeCollation.h>
#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleTextInEx.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseLib.h>
@@ -946,5 +947,17 @@ InternalEfiShellSetEnv(
IN BOOLEAN Volatile
);
+/**
+ Function to start monitoring for CTRL-C using SimpleTextInputEx. This
+ feature's enabled state was not known when the shell initially launched.
+
+ @retval EFI_SUCCESS The feature is enabled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
+**/
+EFI_STATUS
+EFIAPI
+InernalEfiShellStartMonitor(
+ VOID
+ );
#endif //_SHELL_PROTOCOL_HEADER_