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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user