| /** @file | |
| Main file for NULL named library for level 1 shell command functions. | |
| (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR> | |
| Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "UefiShellLevel1CommandsLib.h" | |
| STATIC CONST CHAR16 mFileName[] = L"ShellCommands"; | |
| EFI_HII_HANDLE gShellLevel1HiiHandle = NULL; | |
| /** | |
| Return the help text filename. Only used if no HII information found. | |
| @retval the filename. | |
| **/ | |
| 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 successfully | |
| @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_SUCCESS); | |
| } | |
| gShellLevel1HiiHandle = HiiAddPackages (&gShellLevel1HiiGuid, gImageHandle, UefiShellLevel1CommandsLibStrings, NULL); | |
| if (gShellLevel1HiiHandle == NULL) { | |
| return (EFI_DEVICE_ERROR); | |
| } | |
| // | |
| // install our shell command handlers that are always installed | |
| // | |
| ShellCommandRegisterCommandName (L"stall", ShellCommandRunStall, ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8 (PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN (STR_GET_HELP_STALL))); | |
| 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. | |
| @param ImageHandle The image handle of the process. | |
| @param SystemTable The EFI System Table pointer. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| ShellLevel1CommandsLibDestructor ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ) | |
| { | |
| if (gShellLevel1HiiHandle != NULL) { | |
| HiiRemovePackages (gShellLevel1HiiHandle); | |
| } | |
| return (EFI_SUCCESS); | |
| } | |
| /** | |
| Test a node to see if meets the criterion. | |
| It functions so that count starts at 1 and it increases or decreases when it | |
| hits the specified tags. when it hits zero the location has been found. | |
| DecrementerTag and IncrementerTag are used to get around for/endfor and | |
| similar paired types where the entire middle should be ignored. | |
| If label is used it will be used instead of the count. | |
| @param[in] Function The function to use to enumerate through the | |
| list. Normally GetNextNode or GetPreviousNode. | |
| @param[in] DecrementerTag The tag to decrement the count at. | |
| @param[in] IncrementerTag The tag to increment the count at. | |
| @param[in] Label A label to look for. | |
| @param[in, out] ScriptFile The pointer to the current script file structure. | |
| @param[in] MovePast TRUE makes function return 1 past the found | |
| location. | |
| @param[in] FindOnly TRUE to not change the ScriptFile. | |
| @param[in] CommandNode The pointer to the Node to test. | |
| @param[in, out] TargetCount The pointer to the current count. | |
| **/ | |
| BOOLEAN | |
| TestNodeForMove ( | |
| IN CONST LIST_MANIP_FUNC Function, | |
| IN CONST CHAR16 *DecrementerTag, | |
| IN CONST CHAR16 *IncrementerTag, | |
| IN CONST CHAR16 *Label OPTIONAL, | |
| IN OUT SCRIPT_FILE *ScriptFile, | |
| IN CONST BOOLEAN MovePast, | |
| IN CONST BOOLEAN FindOnly, | |
| IN CONST SCRIPT_COMMAND_LIST *CommandNode, | |
| IN OUT 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); | |
| if (CommandName == NULL) { | |
| return (FALSE); | |
| } | |
| CommandNameWalker = CommandName; | |
| // | |
| // Skip leading spaces and tabs. | |
| // | |
| while ((CommandNameWalker[0] == L' ') || (CommandNameWalker[0] == L'\t')) { | |
| 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); | |
| } | |
| /** | |
| Move the script pointer from 1 tag (line) to another. | |
| It functions so that count starts at 1 and it increases or decreases when it | |
| hits the specified tags. when it hits zero the location has been found. | |
| DecrementerTag and IncrementerTag are used to get around for/endfor and | |
| similar paired types where the entire middle should be ignored. | |
| If label is used it will be used instead of the count. | |
| @param[in] Function The function to use to enumerate through the | |
| list. Normally GetNextNode or GetPreviousNode. | |
| @param[in] DecrementerTag The tag to decrement the count at. | |
| @param[in] IncrementerTag The tag to increment the count at. | |
| @param[in] Label A label to look for. | |
| @param[in, out] ScriptFile The pointer to the current script file structure. | |
| @param[in] MovePast TRUE makes function return 1 past the found | |
| location. | |
| @param[in] FindOnly TRUE to not change the ScriptFile. | |
| @param[in] WrapAroundScript TRUE to wrap end-to-beginning or vise versa in | |
| searching. | |
| **/ | |
| BOOLEAN | |
| MoveToTag ( | |
| IN CONST LIST_MANIP_FUNC Function, | |
| IN CONST CHAR16 *DecrementerTag, | |
| IN CONST CHAR16 *IncrementerTag, | |
| IN CONST CHAR16 *Label OPTIONAL, | |
| IN OUT 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); | |
| } |