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 <Brendan.Jackman@arm.com>
Reviewed-by: Olivier Martin <olivier.martin@arm.com>
Reviewed-by: Jaben Carsey <Jaben.carsey@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15220 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Brendan Jackman
2014-02-11 22:39:49 +00:00
committed by jcarsey
parent 1eb5cf94a1
commit 23385d6319

View File

@@ -759,20 +759,6 @@ GetDevicePathsForImageAndFile (
return (Status); 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. Process all Uefi Shell 2.0 command line options.
@@ -806,95 +792,171 @@ ProcessCommandLine(
VOID VOID
) )
{ {
EFI_STATUS Status; UINTN Size;
LIST_ENTRY *Package; UINTN LoopVar;
UINTN Size; CHAR16 *CurrentArg;
CONST CHAR16 *TempConst; CHAR16 *DelayValueStr;
UINTN Count; UINT64 DelayValue;
UINTN LoopVar; EFI_STATUS Status;
CHAR16 *ProblemParam; EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation;
UINT64 Intermediate;
Package = NULL; // `file-name-options` will contain arguments to `file-name` that we don't
ProblemParam = NULL; // know about. This would cause ShellCommandLineParse to error, so we parse
// arguments manually, ignoring those after the first thing that doesn't look
Status = ShellCommandLineParse (mShellParamList, &Package, NULL, FALSE); // like a shell option (which is assumed to be `file-name`).
Count = 1; Status = gBS->LocateProtocol (
Size = 0; &gEfiUnicodeCollationProtocolGuid,
TempConst = ShellCommandLineGetRawValue(Package, Count++); NULL,
if (TempConst != NULL && StrLen(TempConst)) { (VOID **) &UnicodeCollation
ShellInfoObject.ShellInitSettings.FileName = AllocateZeroPool(StrSize(TempConst)); );
if (ShellInfoObject.ShellInitSettings.FileName == NULL) { if (EFI_ERROR (Status)) {
return (EFI_OUT_OF_RESOURCES); 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); else if (UnicodeCollation->StriColl (
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1; UnicodeCollation,
for (LoopVar = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { L"-nostartup",
if (StrCmp(gEfiShellParametersProtocol->Argv[LoopVar], ShellInfoObject.ShellInitSettings.FileName)==0) { CurrentArg
LoopVar++; ) == 0) {
// ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = TRUE;
// We found the file... add the rest of the params... }
// else if (UnicodeCollation->StriColl (
for ( ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { UnicodeCollation,
ASSERT((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL)); L"-noconsoleout",
StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, CurrentArg
&Size, ) == 0) {
L" ", ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = TRUE;
0); }
if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { else if (UnicodeCollation->StriColl (
SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); UnicodeCollation,
return (EFI_OUT_OF_RESOURCES); L"-noconsolein",
} CurrentArg
StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, ) == 0) {
&Size, ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = TRUE;
gEfiShellParametersProtocol->Argv[LoopVar], }
0); else if (UnicodeCollation->StriColl (
if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) { UnicodeCollation,
SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName); L"-nointerrupt",
return (EFI_OUT_OF_RESOURCES); 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"); // "-nointerrupt" overrides "-delay"
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;
if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) { if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {
ShellInfoObject.ShellInitSettings.Delay = 0; 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;
} }
/** /**