From 23385d63195945990aa1eb18c8659e2bf882aa59 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Tue, 11 Feb 2014 22:39:49 +0000 Subject: [PATCH] ShellPkg: Manually parse parameters We can't use ShellCommandLineParse as it would error out when the shell was called with args like "cp -r foo bar", because "-r" is not a recognised shell option A different way to avoid some of this manual parsing would be to prepend '^' to each argument, but that would still require the degree of parsing necessary to work out which words are part of the command and which are shell options. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brendan Jackman Reviewed-by: Olivier Martin Reviewed-by: Jaben Carsey git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15220 6f19259b-4bc3-4df7-8a09-765794883524 --- ShellPkg/Application/Shell/Shell.c | 244 ++++++++++++++++++----------- 1 file changed, 153 insertions(+), 91 deletions(-) diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c index 18055d5a85..87fd5e15ed 100644 --- a/ShellPkg/Application/Shell/Shell.c +++ b/ShellPkg/Application/Shell/Shell.c @@ -759,20 +759,6 @@ GetDevicePathsForImageAndFile ( return (Status); } -STATIC CONST SHELL_PARAM_ITEM mShellParamList[] = { - {L"-nostartup", TypeFlag}, - {L"-startup", TypeFlag}, - {L"-noconsoleout", TypeFlag}, - {L"-noconsolein", TypeFlag}, - {L"-nointerrupt", TypeFlag}, - {L"-nomap", TypeFlag}, - {L"-noversion", TypeFlag}, - {L"-startup", TypeFlag}, - {L"-delay", TypeValue}, - {L"-_exit", TypeFlag}, - {NULL, TypeMax} - }; - /** Process all Uefi Shell 2.0 command line options. @@ -806,95 +792,171 @@ ProcessCommandLine( VOID ) { - EFI_STATUS Status; - LIST_ENTRY *Package; - UINTN Size; - CONST CHAR16 *TempConst; - UINTN Count; - UINTN LoopVar; - CHAR16 *ProblemParam; - UINT64 Intermediate; + UINTN Size; + UINTN LoopVar; + CHAR16 *CurrentArg; + CHAR16 *DelayValueStr; + UINT64 DelayValue; + EFI_STATUS Status; + EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation; - Package = NULL; - ProblemParam = NULL; - - Status = ShellCommandLineParse (mShellParamList, &Package, NULL, FALSE); + // `file-name-options` will contain arguments to `file-name` that we don't + // know about. This would cause ShellCommandLineParse to error, so we parse + // arguments manually, ignoring those after the first thing that doesn't look + // like a shell option (which is assumed to be `file-name`). - Count = 1; - Size = 0; - TempConst = ShellCommandLineGetRawValue(Package, Count++); - if (TempConst != NULL && StrLen(TempConst)) { - ShellInfoObject.ShellInitSettings.FileName = AllocateZeroPool(StrSize(TempConst)); - if (ShellInfoObject.ShellInitSettings.FileName == NULL) { - return (EFI_OUT_OF_RESOURCES); + Status = gBS->LocateProtocol ( + &gEfiUnicodeCollationProtocolGuid, + NULL, + (VOID **) &UnicodeCollation + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Set default options + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = FALSE; + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = FALSE; + ShellInfoObject.ShellInitSettings.Delay = 5; + + // Start LoopVar at 1 to ignore Argv[0] which is the name of this binary + // (probably "Shell.efi") + for (LoopVar = 1 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { + CurrentArg = gEfiShellParametersProtocol->Argv[LoopVar]; + if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-startup", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = TRUE; } - StrCpy(ShellInfoObject.ShellInitSettings.FileName, TempConst); - ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1; - for (LoopVar = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { - if (StrCmp(gEfiShellParametersProtocol->Argv[LoopVar], ShellInfoObject.ShellInitSettings.FileName)==0) { - LoopVar++; - // - // We found the file... add the rest of the params... - // - for ( ; 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); - } - StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, - &Size, - gEfiShellParametersProtocol->Argv[LoopVar], - 0); - if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { - SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); - return (EFI_OUT_OF_RESOURCES); - } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-nostartup", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-noconsoleout", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-noconsolein", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-nointerrupt", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-nomap", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-noversion", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = TRUE; + } + else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-delay", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = TRUE; + // Check for optional delay value following "-delay" + DelayValueStr = gEfiShellParametersProtocol->Argv[LoopVar + 1]; + if (DelayValueStr != NULL){ + if (*DelayValueStr == L':') { + DelayValueStr++; + } + if (!EFI_ERROR(ShellConvertStringToUint64 ( + DelayValueStr, + &DelayValue, + FALSE, + FALSE + ))) { + ShellInfoObject.ShellInitSettings.Delay = (UINTN)DelayValue; + LoopVar++; + } + } + } else if (UnicodeCollation->StriColl ( + UnicodeCollation, + L"-_exit", + CurrentArg + ) == 0) { + ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = TRUE; + } else if (StrnCmp (L"-", CurrentArg, 1) == 0) { + // Unrecognised option + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_GEN_PROBLEM), + ShellInfoObject.HiiHandle, + CurrentArg + ); + return EFI_INVALID_PARAMETER; + } else { + ShellInfoObject.ShellInitSettings.FileName = AllocateZeroPool(StrSize(CurrentArg)); + if (ShellInfoObject.ShellInitSettings.FileName == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + // + // We found `file-name`. + // + ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1; + + StrCpy (ShellInfoObject.ShellInitSettings.FileName, CurrentArg); + LoopVar++; + + // Add `file-name-options` + for ( ; 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); + } + StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, + &Size, + gEfiShellParametersProtocol->Argv[LoopVar], + 0); + if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { + SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); + return (EFI_OUT_OF_RESOURCES); } } } - } else { - ShellCommandLineFreeVarList(Package); - Package = NULL; - Status = ShellCommandLineParse (mShellParamList, &Package, &ProblemParam, FALSE); - if (EFI_ERROR(Status)) { - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), ShellInfoObject.HiiHandle, ProblemParam); - FreePool(ProblemParam); - ShellCommandLineFreeVarList(Package); - return (EFI_INVALID_PARAMETER); - } } - ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = ShellCommandLineGetFlag(Package, L"-startup"); - ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = ShellCommandLineGetFlag(Package, L"-nostartup"); - ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = ShellCommandLineGetFlag(Package, L"-noconsoleout"); - ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = ShellCommandLineGetFlag(Package, L"-noconsolein"); - ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = ShellCommandLineGetFlag(Package, L"-nointerrupt"); - ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = ShellCommandLineGetFlag(Package, L"-nomap"); - ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = ShellCommandLineGetFlag(Package, L"-noversion"); - ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = ShellCommandLineGetFlag(Package, L"-delay"); - ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = ShellCommandLineGetFlag(Package, L"-_exit"); - - ShellInfoObject.ShellInitSettings.Delay = 5; - + // "-nointerrupt" overrides "-delay" if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) { ShellInfoObject.ShellInitSettings.Delay = 0; - } else if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay) { - TempConst = ShellCommandLineGetValue(Package, L"-delay"); - if (TempConst != NULL && *TempConst == L':') { - TempConst++; - } - if (TempConst != NULL && !EFI_ERROR(ShellConvertStringToUint64(TempConst, &Intermediate, FALSE, FALSE))) { - ShellInfoObject.ShellInitSettings.Delay = (UINTN)Intermediate; - } } - ShellCommandLineFreeVarList(Package); - return (Status); + return EFI_SUCCESS; } /**