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
1 changed files with 153 additions and 91 deletions

View File

@ -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;
}
/**