From a405b86d274d32b92f69842bfb9a1ab143128f57 Mon Sep 17 00:00:00 2001 From: jcarsey Date: Tue, 14 Sep 2010 05:18:09 +0000 Subject: udk2010.up2.shell initial release. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10874 6f19259b-4bc3-4df7-8a09-765794883524 --- ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c | 81 ++ ShellPkg/Library/UefiShellLevel1CommandsLib/For.c | 581 +++++++++++++ ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c | 92 ++ ShellPkg/Library/UefiShellLevel1CommandsLib/If.c | 962 +++++++++++++++++++++ .../UefiShellLevel1CommandsLib/NoOpScriptCommand.c | 40 + .../Library/UefiShellLevel1CommandsLib/Shift.c | 63 ++ .../UefiShellLevel1CommandsLib.c | 251 ++++++ .../UefiShellLevel1CommandsLib.h | 182 ++++ .../UefiShellLevel1CommandsLib.inf | 54 ++ .../UefiShellLevel1CommandsLib.uni | Bin 0 -> 36138 bytes 10 files changed, 2306 insertions(+) create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/For.c create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/If.c create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/NoOpScriptCommand.c create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf create mode 100644 ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni (limited to 'ShellPkg/Library/UefiShellLevel1CommandsLib') diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c new file mode 100644 index 0000000000..2f2a5bf565 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c @@ -0,0 +1,81 @@ +/** @file + Main file for exit shell level 1 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"/b", TypeFlag}, + {NULL, TypeMax} + }; + +/** + Function for 'exit' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunExit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + + // + // If we are in a batch file and /b then pass TRUE otherwise false... + // + ShellCommandRegisterExit((BOOLEAN)(gEfiShellProtocol->BatchIsActive() && ShellCommandLineGetFlag(Package, L"/b"))); + + // + // return the specified error code + // + if (ShellCommandLineGetRawValue(Package, 1) != NULL) { + ShellStatus = (SHELL_STATUS)(ShellStrToUintn(ShellCommandLineGetRawValue(Package, 1))); + } + + ShellCommandLineFreeVarList (Package); + } + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c new file mode 100644 index 0000000000..0e68119b8d --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c @@ -0,0 +1,581 @@ +/** @file + Main file for endfor and for shell level 1 functions. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" +#include + +BOOLEAN +EFIAPI +ShellIsValidForNumber ( + IN CONST CHAR16 *Number + ) +{ + if (Number == NULL || *Number == CHAR_NULL) { + return (FALSE); + } + + if (*Number == L'-') { + Number++; + } + + if (StrLen(Number) == 0) { + return (FALSE); + } + + if (StrLen(Number) >= 7) { + if (StrStr(Number, L" ") != NULL && (StrStr(Number, L" ") - Number) >= 7) { + return (FALSE); + } + } + + if (!ShellIsDecimalDigitCharacter(*Number)) { + return (FALSE); + } + + return (TRUE); +} + +/** + Function for 'endfor' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEndFor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + BOOLEAN Found; + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"EndFor"); + return (SHELL_UNSUPPORTED); + } + + if (gEfiShellParametersProtocol->Argc > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle); + return (SHELL_INVALID_PARAMETER); + } + + Found = MoveToTag(GetPreviousNode, L"for", L"endfor", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE); + + if (!Found) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"For", L"EndFor", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + return (SHELL_NOT_FOUND); + } + return (SHELL_SUCCESS); +} + +typedef struct { + UINT32 Signature; + INTN Current; + INTN End; + INTN Step; + CHAR16 *ReplacementName; + CHAR16 *CurrentValue; + BOOLEAN RemoveSubstAlias; + CHAR16 Set[1]; + } SHELL_FOR_INFO; +#define SIZE_OF_SHELL_FOR_INFO OFFSET_OF (SHELL_FOR_INFO, Set) +#define SHELL_FOR_INFO_SIGNATURE SIGNATURE_32 ('S', 'F', 'I', 's') + +/** + Update the value of a given alias on the list. If the alias is not there then add it. + + @param[in] Alias The alias to test for. + @param[in] CommandString The updated command string. + @param[in,out] List The list to search. +**/ +VOID +EFIAPI +InternalUpdateAliasOnList( + IN CONST CHAR16 *Alias, + IN CONST CHAR16 *CommandString, + IN OUT LIST_ENTRY *List + ) +{ + ALIAS_LIST *Node; + BOOLEAN Found; + + // + // assert for NULL parameter + // + ASSERT(Alias != NULL); + + // + // check for the Alias + // + for ( Node = (ALIAS_LIST *)GetFirstNode(List), Found = FALSE + ; !IsNull(List, &Node->Link) + ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + ASSERT(Node->Alias != NULL); + if (StrCmp(Node->Alias, Alias)==0) { + FreePool(Node->CommandString); + Node->CommandString = NULL; + Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0); + Found = TRUE; + break; + } + } + if (!Found) { + Node = AllocateZeroPool(sizeof(ALIAS_LIST)); + ASSERT(Node->Alias == NULL); + Node->Alias = StrnCatGrow(&Node->Alias, NULL, Alias, 0); + ASSERT(Node->CommandString == NULL); + Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0); + InsertTailList(List, &Node->Link); + } +} + +/** + Find out if an alias is on the given list. + + @param[in] Alias The alias to test for. + @param[in] List The list to search. + + @retval TRUE The alias is on the list. + @retval FALSE The alias is not on the list. +**/ +BOOLEAN +EFIAPI +InternalIsAliasOnList( + IN CONST CHAR16 *Alias, + IN CONST LIST_ENTRY *List + ) +{ + ALIAS_LIST *Node; + + // + // assert for NULL parameter + // + ASSERT(Alias != NULL); + + // + // check for the Alias + // + for ( Node = (ALIAS_LIST *)GetFirstNode(List) + ; !IsNull(List, &Node->Link) + ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + ASSERT(Node->Alias != NULL); + if (StrCmp(Node->Alias, Alias)==0) { + return (TRUE); + } + } + return (FALSE); +} + +/** + Remove an alias from the given list. + + @param[in] Alias The alias to remove. + @param[in,out] List The list to search. +**/ +BOOLEAN +EFIAPI +InternalRemoveAliasFromList( + IN CONST CHAR16 *Alias, + IN OUT LIST_ENTRY *List + ) +{ + ALIAS_LIST *Node; + + // + // assert for NULL parameter + // + ASSERT(Alias != NULL); + + // + // check for the Alias + // + for ( Node = (ALIAS_LIST *)GetFirstNode(List) + ; !IsNull(List, &Node->Link) + ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link) + ){ + ASSERT(Node->CommandString != NULL); + ASSERT(Node->Alias != NULL); + if (StrCmp(Node->Alias, Alias)==0) { + RemoveEntryList(&Node->Link); + FreePool(Node->Alias); + FreePool(Node->CommandString); + FreePool(Node); + return (TRUE); + } + } + return (FALSE); +} + +/** + Function for 'for' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunFor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + SCRIPT_FILE *CurrentScriptFile; + CHAR16 *ArgSet; + CHAR16 *ArgSetWalker; + UINTN ArgSize; + UINTN LoopVar; + SHELL_FOR_INFO *Info; + CHAR16 *TempString; + CHAR16 *TempSpot; + BOOLEAN FirstPass; + EFI_SHELL_FILE_INFO *Node; + EFI_SHELL_FILE_INFO *FileList; + UINTN NewSize; + + ArgSet = NULL; + ArgSize = 0; + ShellStatus = SHELL_SUCCESS; + ArgSetWalker = NULL; + TempString = NULL; + FirstPass = FALSE; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"For"); + return (SHELL_UNSUPPORTED); + } + + if (gEfiShellParametersProtocol->Argc < 4) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle); + return (SHELL_INVALID_PARAMETER); + } + + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + ASSERT(CurrentScriptFile != NULL); + + if (CurrentScriptFile->CurrentCommand->Data == NULL) { + FirstPass = TRUE; + + // + // Make sure that an End exists. + // + if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndFor", L"For", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + return (SHELL_DEVICE_ERROR); + } + + // + // Process the line. + // + if (gEfiShellParametersProtocol->Argv[1][0] != L'%' || gEfiShellParametersProtocol->Argv[1][2] != CHAR_NULL + ||!((gEfiShellParametersProtocol->Argv[1][1] >= L'a' && gEfiShellParametersProtocol->Argv[1][1] <= L'z') + ||(gEfiShellParametersProtocol->Argv[1][1] >= L'A' && gEfiShellParametersProtocol->Argv[1][1] <= L'Z')) + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_VAR), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[2]); + return (SHELL_INVALID_PARAMETER); + } + + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + L"in", + gEfiShellParametersProtocol->Argv[2]) == 0) { + for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { + ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL)); + if (ArgSet == NULL) { + // ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); + } else { + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0); + } + if (StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"*") != NULL + ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"?") != NULL + ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"[") != NULL + ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"]") != NULL) { + FileList = NULL; + Status = ShellOpenFileMetaArg ((CHAR16*)gEfiShellParametersProtocol->Argv[LoopVar], EFI_FILE_MODE_READ, &FileList); + if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) { + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0); + } else { + for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) + ; !IsNull(&FileList->Link, &Node->Link) + ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) + ){ + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0); + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Node->FullName, 0); + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); + } + ShellCloseFileMetaArg(&FileList); + } + } else { + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0); + } + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); + } + // + // set up for an 'in' for loop + // + NewSize = StrSize(ArgSet); + NewSize += sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]); + Info = AllocateZeroPool(NewSize); + ASSERT(Info != NULL); + Info->Signature = SHELL_FOR_INFO_SIGNATURE; + CopyMem(Info->Set, ArgSet, StrSize(ArgSet)); + NewSize = StrSize(gEfiShellParametersProtocol->Argv[1]); + CopyMem(Info->Set+(StrSize(ArgSet)/sizeof(Info->Set[0])), gEfiShellParametersProtocol->Argv[1], NewSize); + Info->ReplacementName = Info->Set+StrSize(ArgSet)/sizeof(Info->Set[0]); + Info->CurrentValue = (CHAR16*)Info->Set; + Info->Step = 0; + Info->Current = 0; + Info->End = 0; + + if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) { + Info->RemoveSubstAlias = FALSE; + } else { + Info->RemoveSubstAlias = TRUE; + } + CurrentScriptFile->CurrentCommand->Data = Info; + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + L"run", + gEfiShellParametersProtocol->Argv[2]) == 0) { + for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { + ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL)); + if (ArgSet == NULL) { +// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); + } else { + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0); + } + ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0); +// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0); + } + // + // set up for a 'run' for loop + // + Info = AllocateZeroPool(sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1])); + ASSERT(Info != NULL); + CopyMem(Info->Set, gEfiShellParametersProtocol->Argv[1], StrSize(gEfiShellParametersProtocol->Argv[1])); + Info->ReplacementName = Info->Set; + Info->CurrentValue = NULL; + ArgSetWalker = ArgSet; + if (ArgSetWalker[0] != L'(') { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ArgSetWalker++; + while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') { + ArgSetWalker++; + } + if (!ShellIsValidForNumber(ArgSetWalker)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ArgSetWalker[0] == L'-') { + Info->Current = 0 - (INTN)ShellStrToUintn(ArgSetWalker+1); + } else { + Info->Current = (INTN)ShellStrToUintn(ArgSetWalker); + } + ArgSetWalker = StrStr(ArgSetWalker, L" "); + while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') { + ArgSetWalker++; + } + if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (ArgSetWalker[0] == L'-') { + Info->End = 0 - (INTN)ShellStrToUintn(ArgSetWalker+1); + } else { + Info->End = (INTN)ShellStrToUintn(ArgSetWalker); + } + if (Info->Current < Info->End) { + Info->Step = 1; + } else { + Info->Step = -1; + } + + ArgSetWalker = StrStr(ArgSetWalker, L" "); + while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') { + ArgSetWalker++; + } + if (ArgSetWalker != NULL && *ArgSetWalker != CHAR_NULL) { + TempSpot = StrStr(ArgSetWalker, L")"); + if (TempSpot == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + *TempSpot = CHAR_NULL; + if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){ + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + if (*ArgSetWalker == L')') { + ASSERT(Info->Step == 1 || Info->Step == -1); + } else { + if (ArgSetWalker[0] == L'-') { + Info->Step = 0 - (INTN)ShellStrToUintn(ArgSetWalker+1); + } else { + Info->Step = (INTN)ShellStrToUintn(ArgSetWalker); + } + } + } + } + } + } + } + } + if (ShellStatus == SHELL_SUCCESS) { + if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) { + Info->RemoveSubstAlias = FALSE; + } else { + Info->RemoveSubstAlias = TRUE; + } + } + CurrentScriptFile->CurrentCommand->Data = Info; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } else { + // + // These need to be NULL since they are used to determine if this is the first pass later on... + // + ASSERT(ArgSetWalker == NULL); + ASSERT(ArgSet == NULL); + } + + Info = (SHELL_FOR_INFO*)CurrentScriptFile->CurrentCommand->Data; + if (CurrentScriptFile->CurrentCommand->Reset) { + Info->CurrentValue = (CHAR16*)Info->Set; + FirstPass = TRUE; + CurrentScriptFile->CurrentCommand->Reset = FALSE; + } + if (ShellStatus == SHELL_SUCCESS) { + ASSERT(Info != NULL); + if (Info->Step != 0) { + // + // only advance if not the first pass + // + if (!FirstPass) { + // + // sequence version of for loop... + // + Info->Current += Info->Step; + } + + TempString = AllocateZeroPool(50*sizeof(CHAR16)); + UnicodeSPrint(TempString, 50*sizeof(CHAR16), L"%d", Info->Current); + InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList); + FreePool(TempString); + + if ((Info->Step > 0 && Info->Current > Info->End) || (Info->Step < 0 && Info->Current < Info->End)) { + CurrentScriptFile->CurrentCommand->Data = NULL; + // + // find the matching endfor (we're done with the loop) + // + if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndFor", L"For", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_DEVICE_ERROR; + } + if (Info->RemoveSubstAlias) { + // + // remove item from list + // + InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList); + } + FreePool(Info); + } + } else { + // + // Must be in 'in' version of for loop... + // + ASSERT(Info->Set != NULL); + if (Info->CurrentValue != NULL && *Info->CurrentValue != CHAR_NULL) { + if (Info->CurrentValue[0] == L'\"') { + Info->CurrentValue++; + } + while (Info->CurrentValue[0] == L' ') { + Info->CurrentValue++; + } + if (Info->CurrentValue[0] == L'\"') { + Info->CurrentValue++; + } + // + // do the next one of the set + // + ASSERT(TempString == NULL); + TempString = StrnCatGrow(&TempString, NULL, Info->CurrentValue, 0); + TempSpot = StrStr(TempString, L"\" \""); + if (TempSpot != NULL) { + *TempSpot = CHAR_NULL; + } + while (TempString[StrLen(TempString)-1] == L'\"') { + TempString[StrLen(TempString)-1] = CHAR_NULL; + } + InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList); + Info->CurrentValue += StrLen(TempString); + + if (Info->CurrentValue[0] == L'\"') { + Info->CurrentValue++; + } + while (Info->CurrentValue[0] == L' ') { + Info->CurrentValue++; + } + if (Info->CurrentValue[0] == L'\"') { + Info->CurrentValue++; + } + FreePool(TempString); + + } else { + CurrentScriptFile->CurrentCommand->Data = NULL; + // + // find the matching endfor (we're done with the loop) + // + if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndFor", L"For", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_DEVICE_ERROR; + } + if (Info->RemoveSubstAlias) { + // + // remove item from list + // + InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList); + } + FreePool(Info); + } + } + } + if (ArgSet != NULL) { + FreePool(ArgSet); + } + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c new file mode 100644 index 0000000000..8213fae7ac --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c @@ -0,0 +1,92 @@ +/** @file + Main file for goto shell level 1 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +/** + Function for 'goto' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunGoto ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + CHAR16 *CompareString; + UINTN Size; + + ShellStatus = SHELL_SUCCESS; + CompareString = NULL; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Goto"); + return (SHELL_UNSUPPORTED); + } + + // + // parse the command line + // + Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + } else { + if (ShellCommandLineGetRawValue(Package, 2) != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Size = 0; + ASSERT((CompareString == NULL && Size == 0) || (CompareString != NULL)); + CompareString = StrnCatGrow(&CompareString, &Size, L":", 0); + CompareString = StrnCatGrow(&CompareString, &Size, ShellCommandLineGetRawValue(Package, 1), 0); + // + // Check forwards and then backwards for a label... + // + if (!MoveToTag(GetNextNode, L"endfor", L"for", CompareString, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, TRUE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, CompareString, L"Goto", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_NOT_FOUND; + } + FreePool(CompareString); + } + ShellCommandLineFreeVarList (Package); + } + + return (ShellStatus); +} + diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c new file mode 100644 index 0000000000..3376329622 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c @@ -0,0 +1,962 @@ +/** @file + Main file for If and else shell level 1 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" +#include + + + + +typedef enum { + END_TAG_OR, + END_TAG_AND, + END_TAG_THEN, + END_TAG_MAX +} END_TAG_TYPE; + +typedef enum { + OPERATOR_GT, + OPERATOR_LT, + OPERATOR_EQ, + OPERATOR_NE, + OPERATOR_GE, + OPERATOR_LE, + OPERATOR_UGT, + OPERATOR_ULT, + OPERATOR_UGE, + OPERATOR_ULE, + OPERATOR_MAX +} BIN_OPERATOR_TYPE; + +BOOLEAN +EFIAPI +IsNextFragment ( + IN CONST CHAR16 **Statement, + IN CONST CHAR16 *Fragment + ) +{ + CHAR16 *Tester; + + Tester = NULL; + + Tester = StrnCatGrow(&Tester, NULL, *Statement, StrLen(Fragment)); + ASSERT(Tester != NULL); + Tester[StrLen(Fragment)] = CHAR_NULL; + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)Fragment, + Tester) == 0) { + // + // increment the string pointer to the end of what we found and then chop off spaces... + // + *Statement+=StrLen(Fragment); + while (*Statement[0] == L' ') { + *Statement++; + } + FreePool(Tester); + return (TRUE); + } + FreePool(Tester); + return (FALSE); +} + +BOOLEAN +EFIAPI +IsValidProfile ( + IN CONST CHAR16 *String + ) +{ + CONST CHAR16 *ProfilesString; + CONST CHAR16 *TempLocation; + + ProfilesString = ShellGetEnvironmentVariable(L"profiles"); + TempLocation = StrStr(ProfilesString, String); + if ((TempLocation != NULL) && (*(TempLocation-1) == L';') && (*(TempLocation+StrLen(String)) == L';')) { + return (TRUE); + } + return (FALSE); +} + +BOOLEAN +EFIAPI +TestOperation ( + IN CONST CHAR16 *Compare1, + IN CONST CHAR16 *Compare2, + IN CONST BIN_OPERATOR_TYPE BinOp, + IN CONST BOOLEAN CaseInsensitive, + IN CONST BOOLEAN ForceStringCompare + ) +{ + INTN Cmp1; + INTN Cmp2; + + // + // "Compare1 BinOp Compare2" + // + switch (BinOp) { + case OPERATOR_UGT: + case OPERATOR_GT: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) > 0) || (StringCompare(&Compare1, &Compare2) > 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1); + } else { + Cmp1 = (INTN)StrDecimalToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1); + } else { + Cmp2 = (INTN)StrDecimalToUintn(Compare2); + } + if (BinOp == OPERATOR_GT) { + if (Cmp1 > Cmp2) { + return (TRUE); + } + } else { + if ((UINTN)Cmp1 > (UINTN)Cmp2) { + return (TRUE); + } + } + } + return (FALSE); + break; + case OPERATOR_ULT: + case OPERATOR_LT: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) < 0) || (StringCompare(&Compare1, &Compare2) < 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1); + } else { + Cmp1 = (INTN)StrDecimalToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1); + } else { + Cmp2 = (INTN)StrDecimalToUintn(Compare2); + } + if (BinOp == OPERATOR_LT) { + if (Cmp1 < Cmp2) { + return (TRUE); + } + } else { + if ((UINTN)Cmp1 < (UINTN)Cmp2) { + return (TRUE); + } + } + + } + return (FALSE); + break; + case OPERATOR_EQ: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) == 0) || (StringCompare(&Compare1, &Compare2) == 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1); + } else { + Cmp1 = (INTN)ShellStrToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1); + } else { + Cmp2 = (INTN)ShellStrToUintn(Compare2); + } + if (Cmp1 == Cmp2) { + return (TRUE); + } + } + return (FALSE); + break; + case OPERATOR_NE: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) != 0) || (StringCompare(&Compare1, &Compare2) != 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1); + } else { + Cmp1 = (INTN)StrDecimalToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1); + } else { + Cmp2 = (INTN)StrDecimalToUintn(Compare2); + } + if (Cmp1 != Cmp2) { + return (TRUE); + } + } + return (FALSE); + break; + case OPERATOR_UGE: + case OPERATOR_GE: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) >= 0) || (StringCompare(&Compare1, &Compare2) >= 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1); + } else { + Cmp1 = (INTN)StrDecimalToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1); + } else { + Cmp2 = (INTN)StrDecimalToUintn(Compare2); + } + if (BinOp == OPERATOR_GE) { + if (Cmp1 >= Cmp2) { + return (TRUE); + } + } else { + if ((UINTN)Cmp1 >= (UINTN)Cmp2) { + return (TRUE); + } + } + } + return (FALSE); + break; + case OPERATOR_LE: + case OPERATOR_ULE: + if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) { + // + // string compare + // + if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) <= 0) || (StringCompare(&Compare1, &Compare2) <= 0)) { + return (TRUE); + } + } else { + // + // numeric compare + // + if (Compare1[0] == L'-') { + Cmp1 = 0 - (INTN)StrDecimalToUintn(Compare1+1); + } else { + Cmp1 = (INTN)StrDecimalToUintn(Compare1); + } + if (Compare2[0] == L'-') { + Cmp2 = 0 - (INTN)StrDecimalToUintn(Compare2+1); + } else { + Cmp2 = (INTN)StrDecimalToUintn(Compare2); + } + if (BinOp == OPERATOR_LE) { + if (Cmp1 <= Cmp2) { + return (TRUE); + } + } else { + if ((UINTN)Cmp1 <= (UINTN)Cmp2) { + return (TRUE); + } + } + } + return (FALSE); + break; + } + ASSERT(FALSE); + return (FALSE); +} + +EFI_STATUS +EFIAPI +ProcessStatement ( + IN OUT BOOLEAN *PassingState, + IN UINTN StartParameterNumber, + IN UINTN EndParameterNumber, + IN CONST END_TAG_TYPE OperatorToUse, + IN CONST BOOLEAN CaseInsensitive, + IN CONST BOOLEAN ForceStringCompare + ) +{ + EFI_STATUS Status; + BOOLEAN OperationResult; + BOOLEAN NotPresent; + CHAR16 *StatementWalker; + BIN_OPERATOR_TYPE BinOp; + CHAR16 *Compare1; + CHAR16 *Compare2; + CHAR16 HexString[20]; + CHAR16 *TempSpot; + + ASSERT((END_TAG_TYPE)OperatorToUse != END_TAG_THEN); + + Status = EFI_SUCCESS; + BinOp = OPERATOR_MAX; + OperationResult = FALSE; + StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber]; + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"not")) { + NotPresent = TRUE; + StatementWalker = gEfiShellParametersProtocol->Argv[++StartParameterNumber]; + } else { + NotPresent = FALSE; + } + + // + // now check for 'boolfunc' operators + // + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"isint")) { + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') { + StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL; + OperationResult = ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE); + } else { + Status = EFI_INVALID_PARAMETER; + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"isint"); + } + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exists") || IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exist")) { + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') { + StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL; + // + // is what remains a file in CWD??? + // + OperationResult = (BOOLEAN)(ShellFileExists(StatementWalker)==EFI_SUCCESS); + } else if (StatementWalker[0] == CHAR_NULL && StartParameterNumber+1 == EndParameterNumber) { + OperationResult = (BOOLEAN)(ShellFileExists(gEfiShellParametersProtocol->Argv[++StartParameterNumber])==EFI_SUCCESS); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"exist(s)"); + Status = EFI_INVALID_PARAMETER; + } + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"available")) { + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') { + StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL; + // + // is what remains a file in the CWD or path??? + // + OperationResult = (BOOLEAN)(ShellIsFileInPath(StatementWalker)==EFI_SUCCESS); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"available"); + Status = EFI_INVALID_PARAMETER; + } + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"profile")) { + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') { + // + // Chop off that ')' + // + StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL; + OperationResult = IsValidProfile(StatementWalker); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"profile"); + Status = EFI_INVALID_PARAMETER; + } + } else if (StartParameterNumber+1 >= EndParameterNumber) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber]); + Status = EFI_INVALID_PARAMETER; + } else { + // + // must be 'item binop item' style + // + Compare1 = NULL; + Compare2 = NULL; + BinOp = OPERATOR_MAX; + + // + // get the first item + // + StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber]; + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) { + TempSpot = StrStr(StatementWalker, L")"); + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) { + *TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT); + ASSERT(Compare1 == NULL); + Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror"); + Status = EFI_INVALID_PARAMETER; + } + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) { + TempSpot = StrStr(StatementWalker, L")"); + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) { + *TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2)); + ASSERT(Compare1 == NULL); + Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror"); + Status = EFI_INVALID_PARAMETER; + } + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) { + TempSpot = StrStr(StatementWalker, L")"); + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) { + TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1)); + ASSERT(Compare1 == NULL); + Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ASSERT(Compare1 == NULL); + if (EndParameterNumber - StartParameterNumber > 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber+2]); + Status = EFI_INVALID_PARAMETER; + } else { + // + // must be a raw string + // + Compare1 = StrnCatGrow(&Compare1, NULL, StatementWalker, 0); + } + } + + // + // get the operator + // + ASSERT(StartParameterNumber+1Argv[StartParameterNumber+1]; + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"gt")) { + BinOp = OPERATOR_GT; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"lt")) { + BinOp = OPERATOR_LT; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"eq")) { + BinOp = OPERATOR_EQ; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ne")) { + BinOp = OPERATOR_NE; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ge")) { + BinOp = OPERATOR_GE; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"le")) { + BinOp = OPERATOR_LE; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"==")) { + BinOp = OPERATOR_EQ; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ugt")) { + BinOp = OPERATOR_UGT; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ult")) { + BinOp = OPERATOR_ULT; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"uge")) { + BinOp = OPERATOR_UGE; + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ule")) { + BinOp = OPERATOR_ULE; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_INVALID_BINOP), gShellLevel1HiiHandle, StatementWalker); + Status = EFI_INVALID_PARAMETER; + } + + // + // get the second item + // + ASSERT(StartParameterNumber+2<=EndParameterNumber); + StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+2]; + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) { + TempSpot = StrStr(StatementWalker, L")"); + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) { + TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT); + ASSERT(Compare2 == NULL); + Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror"); + Status = EFI_INVALID_PARAMETER; + } + // + // can this be collapsed into the above? + // + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) { + TempSpot = StrStr(StatementWalker, L")"); + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) { + TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2)); + ASSERT(Compare2 == NULL); + Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror"); + Status = EFI_INVALID_PARAMETER; + } + } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) { + TempSpot = StrStr(StatementWalker, L")"); + if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) { + TempSpot = CHAR_NULL; + if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) { + UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1)); + ASSERT(Compare2 == NULL); + Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0); + StatementWalker += StrLen(StatementWalker) + 1; + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror"); + Status = EFI_INVALID_PARAMETER; + } + } else { + // + // must be a raw string + // + ASSERT(Compare2 == NULL); + Compare2 = StrnCatGrow(&Compare2, NULL, StatementWalker, 0); + } + + if (Compare1 != NULL && Compare2 != NULL && BinOp != OPERATOR_MAX) { + OperationResult = TestOperation(Compare1, Compare2, BinOp, CaseInsensitive, ForceStringCompare); + } + + SHELL_FREE_NON_NULL(Compare1); + SHELL_FREE_NON_NULL(Compare2); + } + + // + // done processing do result... + // + + if (!EFI_ERROR(Status)) { + if (NotPresent) { + OperationResult = (BOOLEAN)(!OperationResult); + } + switch(OperatorToUse) { + case END_TAG_OR: + *PassingState = (BOOLEAN)(*PassingState || OperationResult); + break; + case END_TAG_AND: + *PassingState = (BOOLEAN)(*PassingState && OperationResult); + break; + case END_TAG_MAX: + *PassingState = (BOOLEAN)(OperationResult); + break; + default: + ASSERT(FALSE); + } + } + return (Status); +} + +BOOLEAN +EFIAPI +BuildNextStatement ( + IN UINTN ParameterNumber, + OUT UINTN *EndParameter, + OUT END_TAG_TYPE *EndTag + ) +{ + CHAR16 *Buffer; + UINTN BufferSize; + + *EndTag = END_TAG_MAX; + + for(Buffer = NULL, BufferSize = 0 + ; ParameterNumber < gEfiShellParametersProtocol->Argc + ; ParameterNumber++ + ) { + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[ParameterNumber], + L"or") == 0) { + *EndParameter = ParameterNumber - 1; + *EndTag = END_TAG_OR; + break; + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[ParameterNumber], + L"and") == 0) { + *EndParameter = ParameterNumber - 1; + *EndTag = END_TAG_AND; + break; + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[ParameterNumber], + L"then") == 0) { + *EndParameter = ParameterNumber - 1; + *EndTag = END_TAG_THEN; + break; + } + } + if (*EndTag == END_TAG_MAX) { + return (FALSE); + } + return (TRUE); +} + +BOOLEAN +EFIAPI +MoveToTagSpecial ( + IN SCRIPT_FILE *ScriptFile + ) +{ + SCRIPT_COMMAND_LIST *CommandNode; + BOOLEAN Found; + UINTN TargetCount; + CHAR16 *CommandName; + CHAR16 *CommandWalker; + CHAR16 *TempLocation; + + TargetCount = 1; + Found = FALSE; + + if (ScriptFile == NULL) { + return FALSE; + } + + for (CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE + ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link) && !Found + ; CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link) + ){ + + // + // get just the first part of the command line... + // + CommandName = NULL; + CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0); + CommandWalker = CommandName; + while (CommandWalker[0] == L' ') { + CommandWalker++; + } + TempLocation = StrStr(CommandWalker, L" "); + + if (TempLocation != NULL) { + *TempLocation = CHAR_NULL; + } + + // + // did we find a nested item ? + // + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandWalker, + L"If") == 0) { + TargetCount++; + } else if (TargetCount == 1 && gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandWalker, + (CHAR16*)L"else") == 0) { + // + // else can only decrement the last part... not an nested if + // hence the TargetCount compare added + // + TargetCount--; + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandWalker, + (CHAR16*)L"endif") == 0) { + TargetCount--; + } + if (TargetCount == 0) { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link); + Found = TRUE; + } + + // + // Free the memory for this loop... + // + SHELL_FREE_NON_NULL(CommandName); + } + return (Found); +} + +EFI_STATUS +EFIAPI +PerformResultOperation ( + IN CONST BOOLEAN Result + ) +{ + if (Result || MoveToTagSpecial(ShellCommandGetCurrentScriptFile())) { + return (EFI_SUCCESS); + } + return (EFI_NOT_FOUND); +} + +/** + Function for 'if' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunIf ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + BOOLEAN CaseInsensitive; + BOOLEAN ForceString; + UINTN CurrentParameter; + UINTN EndParameter; + BOOLEAN CurrentValue; + END_TAG_TYPE Ending; + END_TAG_TYPE PreviousEnding; + + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"If"); + return (SHELL_UNSUPPORTED); + } + + if (gEfiShellParametersProtocol->Argc < 3) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle); + return (SHELL_INVALID_PARAMETER); + } + + // + // Make sure that an End exists. + // + if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, ShellCommandGetCurrentScriptFile(), TRUE, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EnfIf", L"If", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + return (SHELL_DEVICE_ERROR); + } + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + CurrentParameter = 1; + EndParameter = 0; + + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[1], + L"/i") == 0 || + gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[2], + L"/i") == 0 || + (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[3], + L"/i") == 0)) { + CaseInsensitive = TRUE; + CurrentParameter++; + } else { + CaseInsensitive = FALSE; + } + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[1], + L"/s") == 0 || + gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[2], + L"/s") == 0 || + (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[3], + L"/s") == 0)) { + ForceString = TRUE; + CurrentParameter++; + } else { + ForceString = FALSE; + } + + for ( ShellStatus = SHELL_SUCCESS, CurrentValue = FALSE, Ending = END_TAG_MAX + ; CurrentParameter < gEfiShellParametersProtocol->Argc && ShellStatus == SHELL_SUCCESS + ; CurrentParameter++) { + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + gEfiShellParametersProtocol->Argv[CurrentParameter], + L"then") == 0) { + // + // we are at the then + // + if (CurrentParameter+1 != gEfiShellParametersProtocol->Argc) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TEXT_AFTER_THEN), gShellLevel1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + Status = PerformResultOperation(CurrentValue); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]); + ShellStatus = SHELL_INVALID_PARAMETER; + } + } + } else { + PreviousEnding = Ending; + // + // build up the next statement for analysis + // + if (!BuildNextStatement(CurrentParameter, &EndParameter, &Ending)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"Then", L"If", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Analyze the statement + // + Status = ProcessStatement(&CurrentValue, CurrentParameter, EndParameter, PreviousEnding, CaseInsensitive, ForceString); + if (EFI_ERROR(Status)) { +// ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Optomize to get out of the loop early... + // + if ((Ending == END_TAG_OR && CurrentValue) || (Ending == END_TAG_AND && !CurrentValue)) { + Status = PerformResultOperation(CurrentValue); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]); + ShellStatus = SHELL_INVALID_PARAMETER; + } + break; + } + } + } + if (ShellStatus == SHELL_SUCCESS){ + CurrentParameter = EndParameter; + // + // Skip over the or or and parameter. + // + if (Ending == END_TAG_OR || Ending == END_TAG_AND) { + CurrentParameter++; + } + } + } + } + return (ShellStatus); +} + +/** + Function for 'else' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunElse ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + ASSERT_EFI_ERROR(CommandInit()); + + if (gEfiShellParametersProtocol->Argc > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle); + return (SHELL_INVALID_PARAMETER); + } + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Else"); + return (SHELL_UNSUPPORTED); + } + + + if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"If", L"Else", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + return (SHELL_DEVICE_ERROR); + } + if (!MoveToTag(GetPreviousNode, L"if", L"else", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"If", L"Else", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + return (SHELL_DEVICE_ERROR); + } + + if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndIf", "Else", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + return (SHELL_DEVICE_ERROR); + } + + return (SHELL_SUCCESS); +} + +/** + Function for 'endif' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEndIf ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + ASSERT_EFI_ERROR(CommandInit()); + + if (gEfiShellParametersProtocol->Argc > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle); + return (SHELL_INVALID_PARAMETER); + } + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Endif"); + return (SHELL_UNSUPPORTED); + } + + if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"If", L"EndIf", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line); + return (SHELL_DEVICE_ERROR); + } + + return (SHELL_SUCCESS); +} diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/NoOpScriptCommand.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/NoOpScriptCommand.c new file mode 100644 index 0000000000..85fe582579 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/NoOpScriptCommand.c @@ -0,0 +1,40 @@ +/** @file + Main file for else and endif shell level 1 functions. Does nothing really... + + Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +SHELL_STATUS +EFIAPI +ShellCommandRunNoOpScriptCommand ( + VOID *RESERVED + ) +{ + EFI_STATUS Status; + // + // ASSERT that we can init... + // + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + // + // We best be in a script... + // + ASSERT(gEfiShellProtocol->BatchIsActive()); + + // + // Do nothing... + // + return (SHELL_SUCCESS); +} + diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c new file mode 100644 index 0000000000..9abb4c31b1 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c @@ -0,0 +1,63 @@ +/** @file + Main file for Shift shell level 1 function. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +/** + Function for 'shift' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunShift ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + SCRIPT_FILE *CurrentScriptFile; + UINTN LoopVar; + + Status = CommandInit(); + ASSERT_EFI_ERROR(Status); + + if (!gEfiShellProtocol->BatchIsActive()) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Shift"); + return (SHELL_UNSUPPORTED); + } + + CurrentScriptFile = ShellCommandGetCurrentScriptFile(); + ASSERT(CurrentScriptFile != NULL); + + if (CurrentScriptFile->Argc < 2) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle); + return (SHELL_UNSUPPORTED); + } + + for (LoopVar = 0 ; LoopVar < CurrentScriptFile->Argc ; LoopVar++) { + if (LoopVar == 0) { + SHELL_FREE_NON_NULL(CurrentScriptFile->Argv[LoopVar]); + } + if (LoopVar < CurrentScriptFile->Argc -1) { + CurrentScriptFile->Argv[LoopVar] = CurrentScriptFile->Argv[LoopVar+1]; + } else { + CurrentScriptFile->Argv[LoopVar] = NULL; + } + } + CurrentScriptFile->Argc--; + return (SHELL_SUCCESS); +} + diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c new file mode 100644 index 0000000000..47b6f92864 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c @@ -0,0 +1,251 @@ +/** @file + Main file for NULL named library for level 1 shell command functions. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiShellLevel1CommandsLib.h" + +STATIC CONST CHAR16 mFileName[] = L"ShellCommands"; +EFI_HANDLE gShellLevel1HiiHandle = NULL; +CONST EFI_GUID gShellLevel1HiiGuid = \ + { \ + 0xdec5daa4, 0x6781, 0x4820, { 0x9c, 0x63, 0xa7, 0xb0, 0xe4, 0xf1, 0xdb, 0x31 } + }; + + +CONST CHAR16* +EFIAPI +ShellCommandGetManFileNameLevel1 ( + VOID + ) +{ + return (mFileName); +} + +/** + Constructor for the Shell Level 1 Commands library. + + Install the handlers for level 1 UEFI Shell 2.0 commands. + + @param ImageHandle the image handle of the process + @param SystemTable the EFI System Table pointer + + @retval EFI_SUCCESS the shell command handlers were installed sucessfully + @retval EFI_UNSUPPORTED the shell level required was not found. +**/ +EFI_STATUS +EFIAPI +ShellLevel1CommandsLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // if shell level is less than 2 do nothing + // + if (PcdGet8(PcdShellSupportLevel) < 1) { + return (EFI_UNSUPPORTED); + } + + gShellLevel1HiiHandle = HiiAddPackages (&gShellLevel1HiiGuid, gImageHandle, UefiShellLevel1CommandsLibStrings, NULL); + if (gShellLevel1HiiHandle == NULL) { + return (EFI_DEVICE_ERROR); + } + + // + // install our shell command handlers that are always installed + // + ShellCommandRegisterCommandName(L"for", ShellCommandRunFor , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_FOR) )); + ShellCommandRegisterCommandName(L"goto", ShellCommandRunGoto , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_GOTO) )); + ShellCommandRegisterCommandName(L"if", ShellCommandRunIf , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_IF) )); + ShellCommandRegisterCommandName(L"shift", ShellCommandRunShift , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_SHIFT) )); + ShellCommandRegisterCommandName(L"exit", ShellCommandRunExit , ShellCommandGetManFileNameLevel1, 1, L"", TRUE , gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_EXIT) )); + ShellCommandRegisterCommandName(L"else", ShellCommandRunElse , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ELSE) )); + ShellCommandRegisterCommandName(L"endif", ShellCommandRunEndIf , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDIF) )); + ShellCommandRegisterCommandName(L"endfor", ShellCommandRunEndFor , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDFOR))); + + return (EFI_SUCCESS); +} + +/** + Destructor for the library. free any resources. +**/ +EFI_STATUS +EFIAPI +ShellLevel1CommandsLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + if (gShellLevel1HiiHandle != NULL) { + HiiRemovePackages(gShellLevel1HiiHandle); + } + return (EFI_SUCCESS); +} + +BOOLEAN +EFIAPI +TestNodeForMove ( + IN CONST LIST_MANIP_FUNC Function, + IN CONST CHAR16 *DecrementerTag, + IN CONST CHAR16 *IncrementerTag, + IN CONST CHAR16 *Label OPTIONAL, + IN SCRIPT_FILE *ScriptFile, + IN CONST BOOLEAN MovePast, + IN CONST BOOLEAN FindOnly, + IN CONST SCRIPT_COMMAND_LIST *CommandNode, + IN UINTN *TargetCount + ) +{ + BOOLEAN Found; + CHAR16 *CommandName; + CHAR16 *CommandNameWalker; + CHAR16 *TempLocation; + + Found = FALSE; + + // + // get just the first part of the command line... + // + CommandName = NULL; + CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0); + CommandNameWalker = CommandName; + while(CommandNameWalker[0] == L' ') { + CommandNameWalker++; + } + TempLocation = StrStr(CommandNameWalker, L" "); + + if (TempLocation != NULL) { + *TempLocation = CHAR_NULL; + } + + // + // did we find a nested item ? + // + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandNameWalker, + (CHAR16*)IncrementerTag) == 0) { + (*TargetCount)++; + } else if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandNameWalker, + (CHAR16*)DecrementerTag) == 0) { + if (*TargetCount > 0) { + (*TargetCount)--; + } + } + + // + // did we find the matching one... + // + if (Label == NULL) { + if (*TargetCount == 0) { + Found = TRUE; + if (!FindOnly) { + if (MovePast) { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link); + } else { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode; + } + } + } + } else { + if (gUnicodeCollation->StriColl( + gUnicodeCollation, + (CHAR16*)CommandNameWalker, + (CHAR16*)Label) == 0 + && (*TargetCount) == 0) { + Found = TRUE; + if (!FindOnly) { + // + // we found the target label without loops + // + if (MovePast) { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link); + } else { + ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode; + } + } + } + } + + // + // Free the memory for this loop... + // + FreePool(CommandName); + return (Found); +} + +BOOLEAN +EFIAPI +MoveToTag ( + IN CONST LIST_MANIP_FUNC Function, + IN CONST CHAR16 *DecrementerTag, + IN CONST CHAR16 *IncrementerTag, + IN CONST CHAR16 *Label OPTIONAL, + IN SCRIPT_FILE *ScriptFile, + IN CONST BOOLEAN MovePast, + IN CONST BOOLEAN FindOnly, + IN CONST BOOLEAN WrapAroundScript + ) +{ + SCRIPT_COMMAND_LIST *CommandNode; + BOOLEAN Found; + UINTN TargetCount; + + if (Label == NULL) { + TargetCount = 1; + } else { + TargetCount = 0; + } + + if (ScriptFile == NULL) { + return FALSE; + } + + for (CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE + ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link)&& !Found + ; CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link) + ){ + Found = TestNodeForMove( + Function, + DecrementerTag, + IncrementerTag, + Label, + ScriptFile, + MovePast, + FindOnly, + CommandNode, + &TargetCount); + } + + if (WrapAroundScript && !Found) { + for (CommandNode = (SCRIPT_COMMAND_LIST *)GetFirstNode(&ScriptFile->CommandList), Found = FALSE + ; CommandNode != ScriptFile->CurrentCommand && !Found + ; CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link) + ){ + Found = TestNodeForMove( + Function, + DecrementerTag, + IncrementerTag, + Label, + ScriptFile, + MovePast, + FindOnly, + CommandNode, + &TargetCount); + } + } + return (Found); +} + diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h new file mode 100644 index 0000000000..b0aa51bc1b --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h @@ -0,0 +1,182 @@ +/** @file + Main file for NULL named library for level 1 shell command functions. + + Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_HANDLE gShellLevel1HiiHandle; +extern CONST EFI_GUID gShellLevel1HiiGuid; + +/** + Function for 'exit' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunExit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'endif' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEndIf ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'for' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunFor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'endfor' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunEndFor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'if' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunIf ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'goto' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunGoto ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Function for 'shift' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunShift ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Function for 'else' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunElse ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/// +/// Function prototype for BOTH GetNextNode and GetPreviousNode... +/// This is used to control the MoveToTag function direction... +/// +typedef +LIST_ENTRY * +(EFIAPI *LIST_MANIP_FUNC)( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + +/** + Function to move to a spacified tag in a script file structure. + + @param[in] Function The pointer to the function to move with. + @param[in] DecrementerTag The pointer to a string to decrement upon finding. + @param[in] IncrementerTag The pointer to a string to increment upon finding. + @param[in] Label A Label to look for. + @param[in] ScriptFile The script file structure to look in. + @param[in] MovePast TRUE to go to the element just after the found one. FALSE otherwise. + @param[in] FindOnly FALSE to change the execution point in the script file structure. TRUE otherwise. + @param[in] WrapAroundScript TRUE to go to begining when end is hit, or vise versa. FALSE otherwise. +**/ +BOOLEAN +EFIAPI +MoveToTag ( + IN CONST LIST_MANIP_FUNC Function, + IN CONST CHAR16 *DecrementerTag, + IN CONST CHAR16 *IncrementerTag, + IN CONST CHAR16 *Label OPTIONAL, + IN SCRIPT_FILE *ScriptFile, + IN CONST BOOLEAN MovePast, + IN CONST BOOLEAN FindOnly, + IN CONST BOOLEAN WrapAroundScript + ); + diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf new file mode 100644 index 0000000000..b4697f3908 --- /dev/null +++ b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf @@ -0,0 +1,54 @@ +## @file +# Provides shell level 1 functions +# +# Copyright (c) 2009-2010, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +## +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = UefiShellLevel1CommandsLib + FILE_GUID = 50cb6037-1102-47af-b2dd-9944b6eb1abe + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER + CONSTRUCTOR = ShellLevel1CommandsLibConstructor + DESTRUCTOR = ShellLevel1CommandsLibDestructor + +[Sources.common] + UefiShellLevel1CommandsLib.c + UefiShellLevel1CommandsLib.h + UefiShellLevel1CommandsLib.uni + Exit.c + Goto.c + If.c + For.c + Shift.c + +[Packages] + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseLib + BaseMemoryLib + DebugLib + ShellCommandLib + ShellLib + UefiLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + SortLib + PrintLib + +[Pcd.common] + gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel # ALWAYS_CONSUMED diff --git a/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni new file mode 100644 index 0000000000..7043b48ad5 Binary files /dev/null and b/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni differ -- cgit v1.2.3