X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=ShellPkg%2FApplication%2FShell%2FShell.c;h=2adc99240c483f01e5282002122028e5df842e15;hp=3061f8fcbc7e22b155b6c77c8460bad8e0fc6796;hb=e7275d3ffd410943479a9658707ab04d3e9f75ba;hpb=a8f98806ed0e09e15b2654c81ad3f4577b7ab645
diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c
index 3061f8fcbc..2adc99240c 100644
--- a/ShellPkg/Application/Shell/Shell.c
+++ b/ShellPkg/Application/Shell/Shell.c
@@ -1,7 +1,7 @@
/** @file
This is THE shell (application)
- Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.
(C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -33,6 +33,7 @@ SHELL_INFO ShellInfoObject = {
0,
0,
0,
+ 0,
0
}},
0,
@@ -69,6 +70,9 @@ SHELL_INFO ShellInfoObject = {
STATIC CONST CHAR16 mScriptExtension[] = L".NSH";
STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";
STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh";
+CONST CHAR16 mNoNestingEnvVarName[] = L"nonesting";
+CONST CHAR16 mNoNestingTrue[] = L"True";
+CONST CHAR16 mNoNestingFalse[] = L"False";
/**
Cleans off leading and trailing spaces and tabs.
@@ -76,7 +80,6 @@ STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh";
@param[in] String pointer to the string to trim them off.
**/
EFI_STATUS
-EFIAPI
TrimSpaces(
IN CHAR16 **String
)
@@ -109,7 +112,6 @@ TrimSpaces(
@param[in] CheckForEscapeCharacter TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances
**/
CHAR16*
-EFIAPI
FindNextInstance(
IN CONST CHAR16 *SourceString,
IN CONST CHAR16 *FindString,
@@ -123,7 +125,7 @@ FindNextInstance(
Temp = StrStr(SourceString, FindString);
//
- // If nothing found, or we dont care about escape characters
+ // If nothing found, or we don't care about escape characters
//
if (Temp == NULL || !CheckForEscapeCharacter) {
return (Temp);
@@ -143,7 +145,7 @@ FindNextInstance(
}
/**
- Check whether the string between a pair of % is a valid envifronment variable name.
+ Check whether the string between a pair of % is a valid environment variable name.
@param[in] BeginPercent pointer to the first percent.
@param[in] EndPercent pointer to the last percent.
@@ -198,7 +200,6 @@ IsValidEnvironmentVariableName(
@retval FALSE CmdLine does not have a valid split.
**/
BOOLEAN
-EFIAPI
ContainsSplit(
IN CONST CHAR16 *CmdLine
)
@@ -245,10 +246,9 @@ ContainsSplit(
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.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory available.
**/
EFI_STATUS
-EFIAPI
InternalEfiShellStartCtrlSMonitor(
VOID
)
@@ -338,6 +338,7 @@ UefiMain (
UINTN Size;
EFI_HANDLE ConInHandle;
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *OldConIn;
+ SPLIT_LIST *Split;
if (PcdGet8(PcdShellSupportLevel) > 3) {
return (EFI_UNSUPPORTED);
@@ -441,6 +442,8 @@ UefiMain (
Status = CommandInit();
ASSERT_EFI_ERROR(Status);
+ Status = ShellInitEnvVarList ();
+
//
// Check the command line
//
@@ -456,6 +459,29 @@ UefiMain (
Status = ShellCommandCreateInitialMappingsAndPaths();
}
+ //
+ // Set the environment variable for nesting support
+ //
+ Size = 0;
+ TempString = NULL;
+ if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {
+ //
+ // No change. require nesting in Shell Protocol Execute()
+ //
+ StrnCatGrow(&TempString,
+ &Size,
+ L"False",
+ 0);
+ } else {
+ StrnCatGrow(&TempString,
+ &Size,
+ mNoNestingTrue,
+ 0);
+ }
+ Status = InternalEfiShellSetEnv(mNoNestingEnvVarName, TempString, TRUE);
+ SHELL_FREE_NON_NULL(TempString);
+ Size = 0;
+
//
// save the device path for the loaded image and the device path for the filepath (under loaded image)
// These are where to look for the startup.nsh file
@@ -637,7 +663,7 @@ FreeResources:
if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){
InternalEfiShellSetEnv(L"cwd", NULL, TRUE);
}
- CleanUpShellProtocol(ShellInfoObject.NewEfiShellProtocol);
+ CleanUpShellEnvironment (ShellInfoObject.NewEfiShellProtocol);
DEBUG_CODE(ShellInfoObject.NewEfiShellProtocol = NULL;);
}
@@ -646,7 +672,17 @@ FreeResources:
}
if (!IsListEmpty(&ShellInfoObject.SplitList.Link)){
- ASSERT(FALSE); ///@todo finish this de-allocation.
+ ASSERT(FALSE); ///@todo finish this de-allocation (free SplitStdIn/Out when needed).
+
+ for ( Split = (SPLIT_LIST*)GetFirstNode (&ShellInfoObject.SplitList.Link)
+ ; !IsNull (&ShellInfoObject.SplitList.Link, &Split->Link)
+ ; Split = (SPLIT_LIST *)GetNextNode (&ShellInfoObject.SplitList.Link, &Split->Link)
+ ) {
+ RemoveEntryList (&Split->Link);
+ FreePool (Split);
+ }
+
+ DEBUG_CODE (InitializeListHead (&ShellInfoObject.SplitList.Link););
}
if (ShellInfoObject.ShellInitSettings.FileName != NULL) {
@@ -675,6 +711,8 @@ FreeResources:
DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;);
}
+ ShellFreeEnvVarList ();
+
if (ShellCommandGetExit()) {
return ((EFI_STATUS)ShellCommandGetExitCode());
}
@@ -684,11 +722,11 @@ FreeResources:
/**
Sets all the alias' that were registered with the ShellCommandLib library.
- @retval EFI_SUCCESS all init commands were run sucessfully.
+ @retval EFI_SUCCESS all init commands were run successfully.
**/
EFI_STATUS
-EFIAPI
SetBuiltInAlias(
+ VOID
)
{
EFI_STATUS Status;
@@ -726,7 +764,6 @@ SetBuiltInAlias(
@retval FALSE The 2 command names are not the same.
**/
BOOLEAN
-EFIAPI
IsCommand(
IN CONST CHAR16 *Command1,
IN CONST CHAR16 *Command2
@@ -747,7 +784,6 @@ IsCommand(
@retval FALSE The command is not a script only command.
**/
BOOLEAN
-EFIAPI
IsScriptOnlyCommand(
IN CONST CHAR16 *CommandName
)
@@ -769,16 +805,15 @@ IsScriptOnlyCommand(
loaded image protocol installed on it. The FilePath will point to the device path
for the file that was loaded.
- @param[in, out] DevPath On a sucessful return the device path to the loaded image.
- @param[in, out] FilePath On a sucessful return the device path to the file.
+ @param[in, out] DevPath On a successful return the device path to the loaded image.
+ @param[in, out] FilePath On a successful return the device path to the file.
- @retval EFI_SUCCESS The 2 device paths were sucessfully returned.
+ @retval EFI_SUCCESS The 2 device paths were successfully returned.
@retval other A error from gBS->HandleProtocol.
@sa HandleProtocol
**/
EFI_STATUS
-EFIAPI
GetDevicePathsForImageAndFile (
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath,
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
@@ -854,7 +889,6 @@ GetDevicePathsForImageAndFile (
@retval EFI_SUCCESS The variable is initialized.
**/
EFI_STATUS
-EFIAPI
ProcessCommandLine(
VOID
)
@@ -873,12 +907,19 @@ ProcessCommandLine(
// like a shell option (which is assumed to be `file-name`).
Status = gBS->LocateProtocol (
- &gEfiUnicodeCollationProtocolGuid,
+ &gEfiUnicodeCollation2ProtocolGuid,
NULL,
(VOID **) &UnicodeCollation
);
if (EFI_ERROR (Status)) {
- return Status;
+ Status = gBS->LocateProtocol (
+ &gEfiUnicodeCollationProtocolGuid,
+ NULL,
+ (VOID **) &UnicodeCollation
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
}
// Set default options
@@ -891,6 +932,7 @@ ProcessCommandLine(
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = FALSE;
ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = FALSE;
ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = FALSE;
ShellInfoObject.ShellInitSettings.Delay = 5;
//
@@ -950,6 +992,13 @@ ProcessCommandLine(
) == 0) {
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = TRUE;
}
+ else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-nonest",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = TRUE;
+ }
else if (UnicodeCollation->StriColl (
UnicodeCollation,
L"-delay",
@@ -974,12 +1023,12 @@ ProcessCommandLine(
}
} else if (UnicodeCollation->StriColl (
UnicodeCollation,
- L"-_exit",
+ L"-exit",
CurrentArg
) == 0) {
ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = TRUE;
} else if (StrnCmp (L"-", CurrentArg, 1) == 0) {
- // Unrecognised option
+ // Unrecognized option
ShellPrintHiiEx(-1, -1, NULL,
STRING_TOKEN (STR_GEN_PROBLEM),
ShellInfoObject.HiiHandle,
@@ -994,11 +1043,31 @@ ProcessCommandLine(
continue;
}
- ShellInfoObject.ShellInitSettings.FileName = AllocateCopyPool(StrSize(CurrentArg), CurrentArg);
+ ShellInfoObject.ShellInitSettings.FileName = NULL;
+ Size = 0;
+ //
+ // If first argument contains a space, then add double quotes before the argument
+ //
+ if (StrStr (CurrentArg, L" ") != NULL) {
+ StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileName, &Size, L"\"", 0);
+ if (ShellInfoObject.ShellInitSettings.FileName == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ }
+ StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileName, &Size, CurrentArg, 0);
if (ShellInfoObject.ShellInitSettings.FileName == NULL) {
return (EFI_OUT_OF_RESOURCES);
}
//
+ // If first argument contains a space, then add double quotes after the argument
+ //
+ if (StrStr (CurrentArg, L" ") != NULL) {
+ StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileName, &Size, L"\"", 0);
+ if (ShellInfoObject.ShellInitSettings.FileName == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ }
+ //
// We found `file-name`.
//
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1;
@@ -1007,13 +1076,28 @@ ProcessCommandLine(
// Add `file-name-options`
for (Size = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {
ASSERT((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL));
- StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,
- &Size,
- L" ",
- 0);
- if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
- SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);
- return (EFI_OUT_OF_RESOURCES);
+ //
+ // Add a space between arguments
+ //
+ if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {
+ StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, &Size, L" ", 0);
+ if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
+ SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ }
+ //
+ // If an argumnent contains a space, then add double quotes before the argument
+ //
+ if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) {
+ StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,
+ &Size,
+ L"\"",
+ 0);
+ if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
+ SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);
+ return (EFI_OUT_OF_RESOURCES);
+ }
}
StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,
&Size,
@@ -1023,6 +1107,19 @@ ProcessCommandLine(
SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);
return (EFI_OUT_OF_RESOURCES);
}
+ //
+ // If an argumnent contains a space, then add double quotes after the argument
+ //
+ if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) {
+ StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,
+ &Size,
+ L"\"",
+ 0);
+ if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
+ SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ }
}
}
}
@@ -1035,6 +1132,64 @@ ProcessCommandLine(
return EFI_SUCCESS;
}
+/**
+ Function try to find location of the Startup.nsh file.
+
+ The buffer is callee allocated and should be freed by the caller.
+
+ @param ImageDevicePath The path to the image for shell. first place to look for the startup script
+ @param FileDevicePath The path to the file for shell. second place to look for the startup script.
+
+ @retval NULL No Startup.nsh file was found.
+ @return !=NULL Pointer to NULL-terminated path.
+**/
+CHAR16 *
+LocateStartupScript (
+ IN EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *FileDevicePath
+ )
+{
+ CHAR16 *StartupScriptPath;
+ CHAR16 *TempSpot;
+ CONST CHAR16 *MapName;
+ UINTN Size;
+
+ StartupScriptPath = NULL;
+ Size = 0;
+
+ //
+ // Try to find 'Startup.nsh' in the directory where the shell itself was launched.
+ //
+ MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath (&ImageDevicePath);
+ if (MapName != NULL) {
+ StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, MapName, 0);
+ if (StartupScriptPath == NULL) {
+ //
+ // Do not locate the startup script in sys path when out of resource.
+ //
+ return NULL;
+ }
+ TempSpot = StrStr (StartupScriptPath, L";");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+
+ StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, ((FILEPATH_DEVICE_PATH *)FileDevicePath)->PathName, 0);
+ PathRemoveLastItem (StartupScriptPath);
+ StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, mStartupScript, 0);
+ }
+
+ //
+ // Try to find 'Startup.nsh' in the execution path defined by the envrionment variable PATH.
+ //
+ if ((StartupScriptPath == NULL) || EFI_ERROR (ShellIsFile (StartupScriptPath))) {
+ SHELL_FREE_NON_NULL (StartupScriptPath);
+ StartupScriptPath = ShellFindFilePath (mStartupScript);
+ }
+
+ return StartupScriptPath;
+}
+
/**
Handles all interaction with the default startup script.
@@ -1046,26 +1201,20 @@ ProcessCommandLine(
@retval EFI_SUCCESS the variable is initialized.
**/
EFI_STATUS
-EFIAPI
DoStartupScript(
IN EFI_DEVICE_PATH_PROTOCOL *ImagePath,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
)
{
EFI_STATUS Status;
+ EFI_STATUS CalleeStatus;
UINTN Delay;
EFI_INPUT_KEY Key;
- SHELL_FILE_HANDLE FileHandle;
- EFI_DEVICE_PATH_PROTOCOL *NewPath;
- EFI_DEVICE_PATH_PROTOCOL *NamePath;
CHAR16 *FileStringPath;
- CHAR16 *TempSpot;
UINTN NewSize;
- CONST CHAR16 *MapName;
Key.UnicodeChar = CHAR_NULL;
Key.ScanCode = 0;
- FileHandle = NULL;
if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup && ShellInfoObject.ShellInitSettings.FileName != NULL) {
//
@@ -1079,12 +1228,15 @@ DoStartupScript(
if (FileStringPath == NULL) {
return (EFI_OUT_OF_RESOURCES);
}
- StrnCpy(FileStringPath, ShellInfoObject.ShellInitSettings.FileName, NewSize/sizeof(CHAR16) -1);
+ StrCpyS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileName);
if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {
- StrnCat(FileStringPath, L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);
- StrnCat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);
+ StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);
+ StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);
+ }
+ Status = RunShellCommand(FileStringPath, &CalleeStatus);
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit == TRUE) {
+ ShellCommandRegisterExit(gEfiShellProtocol->BatchIsActive(), (UINT64)CalleeStatus);
}
- Status = RunCommand(FileStringPath);
FreePool(FileStringPath);
return (Status);
@@ -1124,60 +1276,17 @@ DoStartupScript(
return (EFI_SUCCESS);
}
- //
- // Try the first location (must be file system)
- //
- MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath(&ImagePath);
- if (MapName != NULL) {
- FileStringPath = NULL;
- NewSize = 0;
- FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, MapName, 0);
- if (FileStringPath == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- } else {
- TempSpot = StrStr(FileStringPath, L";");
- if (TempSpot != NULL) {
- *TempSpot = CHAR_NULL;
- }
- FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, ((FILEPATH_DEVICE_PATH*)FilePath)->PathName, 0);
- PathRemoveLastItem(FileStringPath);
- FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, mStartupScript, 0);
- Status = ShellInfoObject.NewEfiShellProtocol->OpenFileByName(FileStringPath, &FileHandle, EFI_FILE_MODE_READ);
- FreePool(FileStringPath);
- }
- }
- if (EFI_ERROR(Status)) {
- NamePath = FileDevicePath (NULL, mStartupScript);
- NewPath = AppendDevicePathNode (ImagePath, NamePath);
- FreePool(NamePath);
-
+ FileStringPath = LocateStartupScript (ImagePath, FilePath);
+ if (FileStringPath != NULL) {
+ Status = RunScriptFile (FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol);
+ FreePool (FileStringPath);
+ } else {
//
- // Try the location
+ // we return success since startup script is not mandatory.
//
- Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);
- FreePool(NewPath);
- }
- //
- // If we got a file, run it
- //
- if (!EFI_ERROR(Status) && FileHandle != NULL) {
- Status = RunScriptFile (mStartupScript, FileHandle, L"", ShellInfoObject.NewShellParametersProtocol);
- ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);
- } else {
- FileStringPath = ShellFindFilePath(mStartupScript);
- if (FileStringPath == NULL) {
- //
- // we return success since we dont need to have a startup script
- //
- Status = EFI_SUCCESS;
- ASSERT(FileHandle == NULL);
- } else {
- Status = RunScriptFile(FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol);
- FreePool(FileStringPath);
- }
+ Status = EFI_SUCCESS;
}
-
return (Status);
}
@@ -1190,7 +1299,6 @@ DoStartupScript(
@retval RETURN_ABORTED
**/
EFI_STATUS
-EFIAPI
DoShellPrompt (
VOID
)
@@ -1201,6 +1309,7 @@ DoShellPrompt (
CONST CHAR16 *CurDir;
UINTN BufferSize;
EFI_STATUS Status;
+ LIST_ENTRY OldBufferList;
CurDir = NULL;
@@ -1214,6 +1323,7 @@ DoShellPrompt (
return EFI_OUT_OF_RESOURCES;
}
+ SaveBufferList(&OldBufferList);
CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");
//
@@ -1243,6 +1353,7 @@ DoShellPrompt (
//
// Done with this command
//
+ RestoreBufferList(&OldBufferList);
FreePool (CmdLine);
return Status;
}
@@ -1254,8 +1365,7 @@ DoShellPrompt (
@param Buffer Something to pass to FreePool when the shell is exiting.
**/
VOID*
-EFIAPI
-AddBufferToFreeList(
+AddBufferToFreeList (
VOID *Buffer
)
{
@@ -1265,32 +1375,97 @@ AddBufferToFreeList(
return (NULL);
}
- BufferListEntry = AllocateZeroPool(sizeof(BUFFER_LIST));
- ASSERT(BufferListEntry != NULL);
+ BufferListEntry = AllocateZeroPool (sizeof (BUFFER_LIST));
+ if (BufferListEntry == NULL) {
+ return NULL;
+ }
+
BufferListEntry->Buffer = Buffer;
- InsertTailList(&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link);
+ InsertTailList (&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link);
return (Buffer);
}
+
+/**
+ Create a new buffer list and stores the old one to OldBufferList
+
+ @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList.
+**/
+VOID
+SaveBufferList (
+ OUT LIST_ENTRY *OldBufferList
+ )
+{
+ CopyMem (OldBufferList, &ShellInfoObject.BufferToFreeList.Link, sizeof (LIST_ENTRY));
+ InitializeListHead (&ShellInfoObject.BufferToFreeList.Link);
+}
+
+/**
+ Restore previous nodes into BufferToFreeList .
+
+ @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList.
+**/
+VOID
+RestoreBufferList (
+ IN OUT LIST_ENTRY *OldBufferList
+ )
+{
+ FreeBufferList (&ShellInfoObject.BufferToFreeList);
+ CopyMem (&ShellInfoObject.BufferToFreeList.Link, OldBufferList, sizeof (LIST_ENTRY));
+}
+
+
/**
Add a buffer to the Line History List
@param Buffer The line buffer to add.
**/
VOID
-EFIAPI
AddLineToCommandHistory(
IN CONST CHAR16 *Buffer
)
{
BUFFER_LIST *Node;
+ BUFFER_LIST *Walker;
+ UINT16 MaxHistoryCmdCount;
+ UINT16 Count;
+
+ Count = 0;
+ MaxHistoryCmdCount = PcdGet16(PcdShellMaxHistoryCommandCount);
+
+ if (MaxHistoryCmdCount == 0) {
+ return ;
+ }
+
Node = AllocateZeroPool(sizeof(BUFFER_LIST));
- ASSERT(Node != NULL);
- Node->Buffer = AllocateCopyPool(StrSize(Buffer), Buffer);
- ASSERT(Node->Buffer != NULL);
+ if (Node == NULL) {
+ return;
+ }
+
+ Node->Buffer = AllocateCopyPool (StrSize (Buffer), Buffer);
+ if (Node->Buffer == NULL) {
+ FreePool (Node);
+ return;
+ }
- InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);
+ for ( Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link)
+ ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)
+ ; Walker = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)
+ ){
+ Count++;
+ }
+ if (Count < MaxHistoryCmdCount){
+ InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);
+ } else {
+ Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link);
+ RemoveEntryList(&Walker->Link);
+ if (Walker->Buffer != NULL) {
+ FreePool(Walker->Buffer);
+ }
+ FreePool(Walker);
+ InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);
+ }
}
/**
@@ -1307,7 +1482,6 @@ AddLineToCommandHistory(
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
EFI_STATUS
-EFIAPI
ShellConvertAlias(
IN OUT CHAR16 **CommandString
)
@@ -1332,7 +1506,6 @@ ShellConvertAlias(
@param[in,out] CmdLine The command line to update.
**/
EFI_STATUS
-EFIAPI
StripUnreplacedEnvironmentVariables(
IN OUT CHAR16 *CmdLine
)
@@ -1349,7 +1522,7 @@ StripUnreplacedEnvironmentVariables(
SecondPercent = FirstPercent!=NULL?FindNextInstance(FirstPercent+1, L"%", TRUE):NULL;
if (FirstPercent == NULL || SecondPercent == NULL) {
//
- // If we ever dont have 2 % we are done.
+ // If we ever don't have 2 % we are done.
//
break;
}
@@ -1381,7 +1554,7 @@ StripUnreplacedEnvironmentVariables(
//
CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1));
//
- // dont need to update the locator. both % characters are gone.
+ // don't need to update the locator. both % characters are gone.
//
} else {
CurrentLocator = SecondPercent + 1;
@@ -1401,11 +1574,10 @@ StripUnreplacedEnvironmentVariables(
@param[in] OriginalCommandLine The original command line
- @retval NULL An error ocurred.
+ @retval NULL An error occurred.
@return The new command line with no environment variables present.
**/
CHAR16*
-EFIAPI
ShellConvertVariables (
IN CONST CHAR16 *OriginalCommandLine
)
@@ -1442,7 +1614,7 @@ ShellConvertVariables (
; Temp = StrStr(Temp+1, AliasListNode->Alias)
){
//
- // we need a preceeding and if there is space no ^ preceeding (if no space ignore)
+ // we need a preceding and if there is space no ^ preceding (if no space ignore)
//
if ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2)) {
NewSize += StrSize(AliasListNode->CommandString);
@@ -1463,7 +1635,7 @@ ShellConvertVariables (
; Temp = StrStr(Temp+1, MasterEnvList)
){
//
- // we need a preceeding and following % and if there is space no ^ preceeding (if no space ignore)
+ // we need a preceding and following % and if there is space no ^ preceding (if no space ignore)
//
if (*(Temp-1) == L'%' && *(Temp+StrLen(MasterEnvList)) == L'%' &&
((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2))) {
@@ -1475,7 +1647,7 @@ ShellConvertVariables (
//
// now do the replacements...
//
- NewCommandLine1 = AllocateCopyPool(NewSize, OriginalCommandLine);
+ NewCommandLine1 = AllocateZeroPool (NewSize);
NewCommandLine2 = AllocateZeroPool(NewSize);
ItemTemp = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16)));
if (NewCommandLine1 == NULL || NewCommandLine2 == NULL || ItemTemp == NULL) {
@@ -1484,15 +1656,26 @@ ShellConvertVariables (
SHELL_FREE_NON_NULL(ItemTemp);
return (NULL);
}
+ CopyMem (NewCommandLine1, OriginalCommandLine, StrSize (OriginalCommandLine));
+
for (MasterEnvList = EfiShellGetEnv(NULL)
; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL
; MasterEnvList += StrLen(MasterEnvList) + 1
){
- StrnCpy(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1);
- StrnCat(ItemTemp, MasterEnvList, ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp));
- StrnCat(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp));
+ StrCpyS( ItemTemp,
+ ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),
+ L"%"
+ );
+ StrCatS( ItemTemp,
+ ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),
+ MasterEnvList
+ );
+ StrCatS( ItemTemp,
+ ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),
+ L"%"
+ );
ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE);
- StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);
+ StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);
}
if (CurrentScriptFile != NULL) {
for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList)
@@ -1500,12 +1683,12 @@ ShellConvertVariables (
; AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link)
){
ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE);
- StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);
+ StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);
}
}
//
- // Remove non-existant environment variables
+ // Remove non-existent environment variables
//
StripUnreplacedEnvironmentVariables(NewCommandLine1);
@@ -1513,7 +1696,7 @@ ShellConvertVariables (
// Now cleanup any straggler intentionally ignored "%" characters
//
ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE);
- StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);
+ StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);
FreePool(NewCommandLine2);
FreePool(ItemTemp);
@@ -1532,11 +1715,10 @@ ShellConvertVariables (
@retval other Some error occurs when executing the split command.
**/
EFI_STATUS
-EFIAPI
RunSplitCommand(
IN CONST CHAR16 *CmdLine,
- IN SHELL_FILE_HANDLE *StdIn,
- IN SHELL_FILE_HANDLE *StdOut
+ IN SHELL_FILE_HANDLE StdIn,
+ IN SHELL_FILE_HANDLE StdOut
)
{
EFI_STATUS Status;
@@ -1545,7 +1727,7 @@ RunSplitCommand(
UINTN Size1;
UINTN Size2;
SPLIT_LIST *Split;
- SHELL_FILE_HANDLE *TempFileHandle;
+ SHELL_FILE_HANDLE TempFileHandle;
BOOLEAN Unicode;
ASSERT(StdOut == NULL);
@@ -1569,11 +1751,18 @@ RunSplitCommand(
SHELL_FREE_NON_NULL(OurCommandLine);
SHELL_FREE_NON_NULL(NextCommandLine);
return (EFI_INVALID_PARAMETER);
- } else if (NextCommandLine[0] != CHAR_NULL &&
- NextCommandLine[0] == L'a' &&
- NextCommandLine[1] == L' '
- ){
+ } else if (NextCommandLine[0] == L'a' &&
+ (NextCommandLine[1] == L' ' || NextCommandLine[1] == CHAR_NULL)
+ ){
CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0]));
+ while (NextCommandLine[0] == L' ') {
+ CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0]));
+ }
+ if (NextCommandLine[0] == CHAR_NULL) {
+ SHELL_FREE_NON_NULL(OurCommandLine);
+ SHELL_FREE_NON_NULL(NextCommandLine);
+ return (EFI_INVALID_PARAMETER);
+ }
Unicode = FALSE;
} else {
Unicode = TRUE;
@@ -1584,7 +1773,9 @@ RunSplitCommand(
// make a SPLIT_LIST item and add to list
//
Split = AllocateZeroPool(sizeof(SPLIT_LIST));
- ASSERT(Split != NULL);
+ if (Split == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
Split->SplitStdIn = StdIn;
Split->SplitStdOut = ConvertEfiFileProtocolToShellHandle(CreateFileInterfaceMem(Unicode), NULL);
ASSERT(Split->SplitStdOut != NULL);
@@ -1602,7 +1793,7 @@ RunSplitCommand(
Split->SplitStdOut = Split->SplitStdIn;
}
Split->SplitStdIn = TempFileHandle;
- ShellInfoObject.NewEfiShellProtocol->SetFilePosition(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn), 0);
+ ShellInfoObject.NewEfiShellProtocol->SetFilePosition (Split->SplitStdIn, 0);
if (!EFI_ERROR(Status)) {
Status = RunCommand(NextCommandLine);
@@ -1617,11 +1808,11 @@ RunSplitCommand(
//
// Note that the original StdIn is now the StdOut...
//
- if (Split->SplitStdOut != NULL && Split->SplitStdOut != StdIn) {
- ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdOut));
+ if (Split->SplitStdOut != NULL) {
+ ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdOut);
}
if (Split->SplitStdIn != NULL) {
- ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn));
+ ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdIn);
}
FreePool(Split);
@@ -1641,7 +1832,6 @@ RunSplitCommand(
@retval EFI_OUT_OF_RESOURCES a memory allocation failed.
**/
EFI_STATUS
-EFIAPI
ShellSubstituteVariables(
IN CHAR16 **CmdLine
)
@@ -1666,7 +1856,6 @@ ShellSubstituteVariables(
@retval EFI_OUT_OF_RESOURCES a memory allocation failed.
**/
EFI_STATUS
-EFIAPI
ShellSubstituteAliases(
IN CHAR16 **CmdLine
)
@@ -1738,7 +1927,6 @@ ShellSubstituteAliases(
@retval Efi_Application the name is an application (.EFI).
**/
SHELL_OPERATION_TYPES
-EFIAPI
GetOperationType(
IN CONST CHAR16 *CmdName
)
@@ -1807,7 +1995,6 @@ GetOperationType(
@retval EFI_NOT_FOUND The operation type is unknown or invalid.
**/
EFI_STATUS
-EFIAPI
IsValidSplit(
IN CONST CHAR16 *CmdLine
)
@@ -1843,7 +2030,7 @@ IsValidSplit(
return (EFI_OUT_OF_RESOURCES);
}
TempWalker = (CHAR16*)Temp;
- if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine)))) {
+ if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine), TRUE))) {
if (GetOperationType(FirstParameter) == Unknown_Invalid) {
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
SetLastError(SHELL_NOT_FOUND);
@@ -1866,7 +2053,6 @@ IsValidSplit(
@retval EFI_ABORTED CmdLine has at least one invalid command or application.
**/
EFI_STATUS
-EFIAPI
VerifySplit(
IN CONST CHAR16 *CmdLine
)
@@ -1875,24 +2061,31 @@ VerifySplit(
EFI_STATUS Status;
//
- // Verify up to the pipe or end character
+ // If this was the only item, then get out
//
- Status = IsValidSplit(CmdLine);
- if (EFI_ERROR(Status)) {
- return (Status);
+ if (!ContainsSplit(CmdLine)) {
+ return (EFI_SUCCESS);
}
//
- // If this was the only item, then get out
+ // Verify up to the pipe or end character
//
- if (!ContainsSplit(CmdLine)) {
- return (EFI_SUCCESS);
+ Status = IsValidSplit(CmdLine);
+ if (EFI_ERROR(Status)) {
+ return (Status);
}
//
// recurse to verify the next item
//
TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1;
+ if (*TempSpot == L'a' &&
+ (*(TempSpot + 1) == L' ' || *(TempSpot + 1) == CHAR_NULL)
+ ) {
+ // If it's an ASCII pipe '|a'
+ TempSpot += 1;
+ }
+
return (VerifySplit(TempSpot));
}
@@ -1902,10 +2095,9 @@ VerifySplit(
@param[in] CmdLine pointer to the command line to process
@retval EFI_SUCCESS The operation was successful
- @return an error occured.
+ @return an error occurred.
**/
EFI_STATUS
-EFIAPI
ProcessNewSplitCommandLine(
IN CONST CHAR16 *CmdLine
)
@@ -1946,7 +2138,6 @@ ProcessNewSplitCommandLine(
@retval EFI_SUCCESS The operation was successful.
**/
EFI_STATUS
-EFIAPI
ChangeMappedDrive(
IN CONST CHAR16 *CmdLine
)
@@ -1982,7 +2173,6 @@ ChangeMappedDrive(
@param[in,out] CmdLine pointer to the command line to update
**/
EFI_STATUS
-EFIAPI
DoHelpUpdate(
IN OUT CHAR16 **CmdLine
)
@@ -1991,6 +2181,7 @@ DoHelpUpdate(
CHAR16 *Walker;
CHAR16 *NewCommandLine;
EFI_STATUS Status;
+ UINTN NewCmdLineSize;
Status = EFI_SUCCESS;
@@ -2001,11 +2192,12 @@ DoHelpUpdate(
Walker = *CmdLine;
while(Walker != NULL && *Walker != CHAR_NULL) {
- if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine)))) {
+ if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine), TRUE))) {
if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {
CurrentParameter[0] = L' ';
CurrentParameter[1] = L' ';
- NewCommandLine = AllocateZeroPool(StrSize(L"help ") + StrSize(*CmdLine));
+ NewCmdLineSize = StrSize(L"help ") + StrSize(*CmdLine);
+ NewCommandLine = AllocateZeroPool(NewCmdLineSize);
if (NewCommandLine == NULL) {
Status = EFI_OUT_OF_RESOURCES;
break;
@@ -2014,8 +2206,8 @@ DoHelpUpdate(
//
// We know the space is sufficient since we just calculated it.
//
- StrnCpy(NewCommandLine, L"help ", 5);
- StrnCat(NewCommandLine, *CmdLine, StrLen(*CmdLine));
+ StrnCpyS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), L"help ", 5);
+ StrnCatS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), *CmdLine, StrLen(*CmdLine));
SHELL_FREE_NON_NULL(*CmdLine);
*CmdLine = NewCommandLine;
break;
@@ -2034,7 +2226,6 @@ DoHelpUpdate(
@param[in] ErrorCode the error code to put into lasterror.
**/
EFI_STATUS
-EFIAPI
SetLastError(
IN CONST SHELL_STATUS ErrorCode
)
@@ -2058,10 +2249,9 @@ SetLastError(
@retval EFI_SUCCESS The operation was successful
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @return some other error occured
+ @return some other error occurred
**/
EFI_STATUS
-EFIAPI
ProcessCommandLineToFinal(
IN OUT CHAR16 **CmdLine
)
@@ -2103,21 +2293,22 @@ ProcessCommandLineToFinal(
/**
Run an internal shell command.
- This API will upadate the shell's environment since these commands are libraries.
+ This API will update the shell's environment since these commands are libraries.
@param[in] CmdLine the command line to run.
@param[in] FirstParameter the first parameter on the command line
@param[in] ParamProtocol the shell parameters protocol pointer
+ @param[out] CommandStatus the status from the command line.
@retval EFI_SUCCESS The command was completed.
@retval EFI_ABORTED The command's operation was aborted.
**/
EFI_STATUS
-EFIAPI
RunInternalCommand(
IN CONST CHAR16 *CmdLine,
IN CHAR16 *FirstParameter,
- IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
+ OUT EFI_STATUS *CommandStatus
)
{
EFI_STATUS Status;
@@ -2142,7 +2333,7 @@ RunInternalCommand(
//
// get the argc and argv updated for internal commands
//
- Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, &Argv, &Argc);
+ Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, Internal_Command, &Argv, &Argc);
if (!EFI_ERROR(Status)) {
//
// Run the internal command.
@@ -2150,6 +2341,14 @@ RunInternalCommand(
Status = ShellCommandRunCommandHandler(FirstParameter, &CommandReturnedStatus, &LastError);
if (!EFI_ERROR(Status)) {
+ if (CommandStatus != NULL) {
+ if (CommandReturnedStatus != SHELL_SUCCESS) {
+ *CommandStatus = (EFI_STATUS)(CommandReturnedStatus | MAX_BIT);
+ } else {
+ *CommandStatus = EFI_SUCCESS;
+ }
+ }
+
//
// Update last error status.
// some commands do not update last error.
@@ -2181,13 +2380,13 @@ RunInternalCommand(
}
//
- // This is guarenteed to be called after UpdateArgcArgv no matter what else happened.
+ // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.
// This is safe even if the update API failed. In this case, it may be a no-op.
//
RestoreArgcArgv(ParamProtocol, &Argv, &Argc);
//
- // If a script is running and the command is not a scipt only command, then
+ // If a script is running and the command is not a script only command, then
// change return value to success so the script won't halt (unless aborted).
//
// Script only commands have to be able halt the script since the script will
@@ -2211,17 +2410,18 @@ RunInternalCommand(
@param[in] CmdLine the command line to run.
@param[in] FirstParameter the first parameter on the command line
@param[in] ParamProtocol the shell parameters protocol pointer
+ @param[out] CommandStatus the status from the command line.
@retval EFI_SUCCESS The command was completed.
@retval EFI_ABORTED The command's operation was aborted.
**/
EFI_STATUS
-EFIAPI
RunCommandOrFile(
IN SHELL_OPERATION_TYPES Type,
IN CONST CHAR16 *CmdLine,
IN CHAR16 *FirstParameter,
- IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
+ OUT EFI_STATUS *CommandStatus
)
{
EFI_STATUS Status;
@@ -2237,7 +2437,7 @@ RunCommandOrFile(
switch (Type) {
case Internal_Command:
- Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol);
+ Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol, CommandStatus);
break;
case Script_File_Name:
case Efi_Application:
@@ -2303,6 +2503,10 @@ RunCommandOrFile(
CalleeExitStatus = (SHELL_STATUS) StartStatus;
}
+ if (CommandStatus != NULL) {
+ *CommandStatus = CalleeExitStatus;
+ }
+
//
// Update last error status.
//
@@ -2335,17 +2539,18 @@ RunCommandOrFile(
@param[in] CmdLine the command line to run.
@param[in] FirstParameter the first parameter on the command line.
@param[in] ParamProtocol the shell parameters protocol pointer
+ @param[out] CommandStatus the status from the command line.
@retval EFI_SUCCESS The command was completed.
@retval EFI_ABORTED The command's operation was aborted.
**/
EFI_STATUS
-EFIAPI
SetupAndRunCommandOrFile(
- IN SHELL_OPERATION_TYPES Type,
- IN CHAR16 *CmdLine,
- IN CHAR16 *FirstParameter,
- IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
+ IN SHELL_OPERATION_TYPES Type,
+ IN CHAR16 *CmdLine,
+ IN CHAR16 *FirstParameter,
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
+ OUT EFI_STATUS *CommandStatus
)
{
EFI_STATUS Status;
@@ -2353,6 +2558,7 @@ SetupAndRunCommandOrFile(
SHELL_FILE_HANDLE OriginalStdOut;
SHELL_FILE_HANDLE OriginalStdErr;
SYSTEM_TABLE_INFO OriginalSystemTableInfo;
+ CONST SCRIPT_FILE *ConstScriptFile;
//
// Update the StdIn, StdOut, and StdErr for redirection to environment variables, files, etc... unicode and ASCII
@@ -2365,14 +2571,19 @@ SetupAndRunCommandOrFile(
//
if (!EFI_ERROR(Status)) {
TrimSpaces(&CmdLine);
- Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol);
+ Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol, CommandStatus);
}
//
// Now print errors
//
if (EFI_ERROR(Status)) {
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID*)(Status));
+ ConstScriptFile = ShellCommandGetCurrentScriptFile();
+ if (ConstScriptFile == NULL || ConstScriptFile->CurrentCommand == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID*)(Status));
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR_SCRIPT), ShellInfoObject.HiiHandle, (VOID*)(Status), ConstScriptFile->CurrentCommand->Line);
+ }
}
//
@@ -2390,14 +2601,15 @@ SetupAndRunCommandOrFile(
command or dispatch an external application.
@param[in] CmdLine The command line to parse.
+ @param[out] CommandStatus The status from the command line.
@retval EFI_SUCCESS The command was completed.
@retval EFI_ABORTED The command's operation was aborted.
**/
EFI_STATUS
-EFIAPI
-RunCommand(
- IN CONST CHAR16 *CmdLine
+RunShellCommand(
+ IN CONST CHAR16 *CmdLine,
+ OUT EFI_STATUS *CommandStatus
)
{
EFI_STATUS Status;
@@ -2405,6 +2617,7 @@ RunCommand(
CHAR16 *FirstParameter;
CHAR16 *TempWalker;
SHELL_OPERATION_TYPES Type;
+ CONST CHAR16 *CurDir;
ASSERT(CmdLine != NULL);
if (StrLen(CmdLine) == 0) {
@@ -2425,7 +2638,7 @@ RunCommand(
// NULL out comments (leveraged from RunScriptFileHandle() ).
// The # character on a line is used to denote that all characters on the same line
// and to the right of the # are to be ignored by the shell.
- // Afterward, again remove spaces, in case any were between the last command-parameter and '#'.
+ // Afterwards, again remove spaces, in case any were between the last command-parameter and '#'.
//
for (TempWalker = CleanOriginal; TempWalker != NULL && *TempWalker != CHAR_NULL; TempWalker++) {
if (*TempWalker == L'^') {
@@ -2454,7 +2667,7 @@ RunCommand(
}
//
- // We dont do normal processing with a split command line (output from one command input to another)
+ // We don't do normal processing with a split command line (output from one command input to another)
//
if (ContainsSplit(CleanOriginal)) {
Status = ProcessNewSplitCommandLine(CleanOriginal);
@@ -2471,7 +2684,7 @@ RunCommand(
return (EFI_OUT_OF_RESOURCES);
}
TempWalker = CleanOriginal;
- if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal)))) {
+ if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal), TRUE))) {
//
// Depending on the first parameter we change the behavior
//
@@ -2482,7 +2695,7 @@ RunCommand(
case Internal_Command:
case Script_File_Name:
case Efi_Application:
- Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol);
+ Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol, CommandStatus);
break;
default:
//
@@ -2496,16 +2709,51 @@ RunCommand(
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
SetLastError(SHELL_NOT_FOUND);
}
-
+ //
+ // Check whether the current file system still exists. If not exist, we need update "cwd" and gShellCurMapping.
+ //
+ CurDir = EfiShellGetCurDir (NULL);
+ if (CurDir != NULL) {
+ if (EFI_ERROR(ShellFileExists (CurDir))) {
+ //
+ // EfiShellSetCurDir() cannot set current directory to NULL.
+ // EfiShellSetEnv() is not allowed to set the "cwd" variable.
+ // Only InternalEfiShellSetEnv () is allowed setting the "cwd" variable.
+ //
+ InternalEfiShellSetEnv (L"cwd", NULL, TRUE);
+ gShellCurMapping = NULL;
+ }
+ }
+
SHELL_FREE_NON_NULL(CleanOriginal);
SHELL_FREE_NON_NULL(FirstParameter);
return (Status);
}
+/**
+ Function will process and run a command line.
+
+ This will determine if the command line represents an internal shell
+ command or dispatch an external application.
+
+ @param[in] CmdLine The command line to parse.
+
+ @retval EFI_SUCCESS The command was completed.
+ @retval EFI_ABORTED The command's operation was aborted.
+**/
+EFI_STATUS
+RunCommand(
+ IN CONST CHAR16 *CmdLine
+ )
+{
+ return (RunShellCommand(CmdLine, NULL));
+}
+
+
STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"', 0x0001, 0x0002};
/**
- Function determins if the CommandName COULD be a valid command. It does not determine whether
+ Function determines if the CommandName COULD be a valid command. It does not determine whether
this is a valid command. It only checks for invalid characters.
@param[in] CommandName The name to check
@@ -2514,7 +2762,6 @@ STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"'
@retval FALSE CommandName could not be a valid command name
**/
BOOLEAN
-EFIAPI
IsValidCommandName(
IN CONST CHAR16 *CommandName
)
@@ -2541,10 +2788,9 @@ IsValidCommandName(
@param[in] Handle The handle to the already opened file.
@param[in] Name The name of the script file.
- @retval EFI_SUCCESS the script completed sucessfully
+ @retval EFI_SUCCESS the script completed successfully
**/
EFI_STATUS
-EFIAPI
RunScriptFileHandle (
IN SHELL_FILE_HANDLE Handle,
IN CONST CHAR16 *Name
@@ -2553,6 +2799,7 @@ RunScriptFileHandle (
EFI_STATUS Status;
SCRIPT_FILE *NewScriptFile;
UINTN LoopVar;
+ UINTN PrintBuffSize;
CHAR16 *CommandLine;
CHAR16 *CommandLine2;
CHAR16 *CommandLine3;
@@ -2563,10 +2810,12 @@ RunScriptFileHandle (
CONST CHAR16 *CurDir;
UINTN LineCount;
CHAR16 LeString[50];
+ LIST_ENTRY OldBufferList;
ASSERT(!ShellCommandGetScriptExit());
PreScriptEchoState = ShellCommandGetEchoState();
+ PrintBuffSize = PcdGet16(PcdShellPrintBufferSize);
NewScriptFile = (SCRIPT_FILE*)AllocateZeroPool(sizeof(SCRIPT_FILE));
if (NewScriptFile == NULL) {
@@ -2641,12 +2890,12 @@ RunScriptFileHandle (
//
// Now enumerate through the commands and run each one.
//
- CommandLine = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));
+ CommandLine = AllocateZeroPool(PrintBuffSize);
if (CommandLine == NULL) {
DeleteScriptFileStruct(NewScriptFile);
return (EFI_OUT_OF_RESOURCES);
}
- CommandLine2 = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));
+ CommandLine2 = AllocateZeroPool(PrintBuffSize);
if (CommandLine2 == NULL) {
FreePool(CommandLine);
DeleteScriptFileStruct(NewScriptFile);
@@ -2658,7 +2907,13 @@ RunScriptFileHandle (
; // conditional increment in the body of the loop
){
ASSERT(CommandLine2 != NULL);
- StrnCpy(CommandLine2, NewScriptFile->CurrentCommand->Cl, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1);
+ StrnCpyS( CommandLine2,
+ PrintBuffSize/sizeof(CHAR16),
+ NewScriptFile->CurrentCommand->Cl,
+ PrintBuffSize/sizeof(CHAR16) - 1
+ );
+
+ SaveBufferList(&OldBufferList);
//
// NULL out comments
@@ -2679,7 +2934,11 @@ RunScriptFileHandle (
//
// Due to variability in starting the find and replace action we need to have both buffers the same.
//
- StrnCpy(CommandLine, CommandLine2, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1);
+ StrnCpyS( CommandLine,
+ PrintBuffSize/sizeof(CHAR16),
+ CommandLine2,
+ PrintBuffSize/sizeof(CHAR16) - 1
+ );
//
// Remove the %0 to %9 from the command line (if we have some arguments)
@@ -2687,51 +2946,55 @@ RunScriptFileHandle (
if (NewScriptFile->Argv != NULL) {
switch (NewScriptFile->Argc) {
default:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
case 9:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
case 8:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
case 7:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
case 6:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
case 5:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
case 4:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
case 3:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
case 2:
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
case 1:
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE, TRUE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, FALSE);
ASSERT_EFI_ERROR(Status);
break;
case 0:
break;
}
}
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", L"\"\"", FALSE, FALSE);
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", L"\"\"", FALSE, FALSE);
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", L"\"\"", FALSE, FALSE);
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", L"\"\"", FALSE, FALSE);
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", L"\"\"", FALSE, FALSE);
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", L"\"\"", FALSE, FALSE);
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", L"\"\"", FALSE, FALSE);
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", L"\"\"", FALSE, FALSE);
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", L"\"\"", FALSE, FALSE);
-
- StrnCpy(CommandLine2, CommandLine, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%8", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%9", L"\"\"", FALSE, FALSE);
+
+ StrnCpyS( CommandLine2,
+ PrintBuffSize/sizeof(CHAR16),
+ CommandLine,
+ PrintBuffSize/sizeof(CHAR16) - 1
+ );
LastCommand = NewScriptFile->CurrentCommand;
@@ -2786,15 +3049,19 @@ RunScriptFileHandle (
ShellCommandRegisterExit(FALSE, 0);
Status = EFI_SUCCESS;
+ RestoreBufferList(&OldBufferList);
break;
}
if (ShellGetExecutionBreakFlag()) {
+ RestoreBufferList(&OldBufferList);
break;
}
if (EFI_ERROR(Status)) {
+ RestoreBufferList(&OldBufferList);
break;
}
if (ShellCommandGetExit()) {
+ RestoreBufferList(&OldBufferList);
break;
}
}
@@ -2813,6 +3080,7 @@ RunScriptFileHandle (
NewScriptFile->CurrentCommand->Reset = TRUE;
}
}
+ RestoreBufferList(&OldBufferList);
}
@@ -2837,10 +3105,9 @@ RunScriptFileHandle (
@param[in] CmdLine the command line to run.
@param[in] ParamProtocol the shell parameters protocol pointer
- @retval EFI_SUCCESS the script completed sucessfully
+ @retval EFI_SUCCESS the script completed successfully
**/
EFI_STATUS
-EFIAPI
RunScriptFile (
IN CONST CHAR16 *ScriptPath,
IN SHELL_FILE_HANDLE Handle OPTIONAL,
@@ -2860,7 +3127,7 @@ RunScriptFile (
//
// get the argc and argv updated for scripts
//
- Status = UpdateArgcArgv(ParamProtocol, CmdLine, &Argv, &Argc);
+ Status = UpdateArgcArgv(ParamProtocol, CmdLine, Script_File_Name, &Argv, &Argc);
if (!EFI_ERROR(Status)) {
if (Handle == NULL) {
@@ -2885,7 +3152,7 @@ RunScriptFile (
}
//
- // This is guarenteed to be called after UpdateArgcArgv no matter what else happened.
+ // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.
// This is safe even if the update API failed. In this case, it may be a no-op.
//
RestoreArgcArgv(ParamProtocol, &Argv, &Argc);
@@ -2894,7 +3161,7 @@ RunScriptFile (
}
/**
- Return the pointer to the first occurance of any character from a list of characters.
+ Return the pointer to the first occurrence of any character from a list of characters.
@param[in] String the string to parse
@param[in] CharacterList the list of character to look for
@@ -2904,7 +3171,6 @@ RunScriptFile (
@retval CHAR_NULL no instance of any character in CharacterList was found in String
**/
CONST CHAR16*
-EFIAPI
FindFirstCharacter(
IN CONST CHAR16 *String,
IN CONST CHAR16 *CharacterList,
@@ -2926,4 +3192,4 @@ FindFirstCharacter(
}
}
return (String + StrLen(String));
-}
\ No newline at end of file
+}