manipulation, and initialization of EFI_SHELL_PROTOCOL.\r
\r
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
- Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
@retval FALSE gEfiBlockIoProtocolGuid was not found.\r
**/\r
BOOLEAN\r
-EFIAPI\r
InternalShellProtocolIsBlockIoPresent(\r
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
)\r
@retval FALSE gEfiSimpleFileSystemProtocolGuid was not found.\r
**/\r
BOOLEAN\r
-EFIAPI\r
InternalShellProtocolIsSimpleFileSystemPresent(\r
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
)\r
return (FALSE);\r
}\r
\r
-/**\r
- Internal worker debug helper function to print out maps as they are added.\r
-\r
- @param[in] Mapping string mapping that has been added\r
- @param[in] DevicePath pointer to device path that has been mapped.\r
-\r
- @retval EFI_SUCCESS the operation was successful.\r
- @return other an error ocurred\r
-\r
- @sa LocateHandle\r
- @sa OpenProtocol\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InternalShellProtocolDebugPrintMessage (\r
- IN CONST CHAR16 *Mapping,\r
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- CHAR16 *Temp;\r
-\r
- Status = EFI_SUCCESS;\r
- DEBUG_CODE_BEGIN();\r
-\r
- if (Mapping != NULL) {\r
- DEBUG((EFI_D_INFO, "Added new map item:\"%S\"\r\n", Mapping));\r
- }\r
- Temp = ConvertDevicePathToText(DevicePath, TRUE, TRUE);\r
- DEBUG((EFI_D_INFO, "DevicePath: %S\r\n", Temp));\r
- FreePool(Temp);\r
-\r
- DEBUG_CODE_END();\r
- return (Status);\r
-}\r
\r
/**\r
This function creates a mapping for a device path.\r
\r
- If both DeviecPath and Mapping are NULL, this will reset the mapping to default values.\r
+ If both DevicePath and Mapping are NULL, this will reset the mapping to default values.\r
\r
@param DevicePath Points to the device path. If this is NULL and Mapping points to a valid mapping,\r
then the mapping will be deleted.\r
){\r
if (StringNoCaseCompare(&MapListNode->MapName, &Mapping) == 0) {\r
RemoveEntryList(&MapListNode->Link);\r
+ SHELL_FREE_NON_NULL(MapListNode->DevicePath);\r
+ SHELL_FREE_NON_NULL(MapListNode->MapName);\r
+ SHELL_FREE_NON_NULL(MapListNode->CurrentDirectoryPath);\r
FreePool(MapListNode);\r
return (EFI_SUCCESS);\r
}\r
} // for loop\r
\r
//\r
- // We didnt find one to delete\r
+ // We didn't find one to delete\r
//\r
return (EFI_NOT_FOUND);\r
}\r
device path. If there is an exact match, the mapping is returned and *DevicePath\r
points to the end-of-device-path node.\r
\r
- If there are multiple map names they will be semi-colon seperated in the\r
+ If there are multiple map names they will be semi-colon separated in the\r
NULL-terminated string.\r
\r
@param DevicePath On entry, points to a device path pointer. On\r
; FilePath = (FILEPATH_DEVICE_PATH*)NextDevicePathNode (&FilePath->Header)\r
){\r
//\r
- // all the rest should be file path nodes\r
+ // If any node is not a file path node, then the conversion can not be completed\r
//\r
if ((DevicePathType(&FilePath->Header) != MEDIA_DEVICE_PATH) ||\r
(DevicePathSubType(&FilePath->Header) != MEDIA_FILEPATH_DP)) {\r
FreePool(PathForReturn);\r
- PathForReturn = NULL;\r
- ASSERT(FALSE);\r
- } else {\r
- //\r
- // append the path part onto the filepath.\r
- //\r
- ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
-\r
- AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
- ASSERT (AlignedNode != NULL);\r
-\r
- // File Path Device Path Nodes 'can optionally add a "\" separator to\r
- // the beginning and/or the end of the Path Name string.'\r
- // (UEFI Spec 2.4 section 9.3.6.4).\r
- // If necessary, add a "\", but otherwise don't\r
- // (This is specified in the above section, and also implied by the\r
- // UEFI Shell spec section 3.7)\r
- if ((PathSize != 0) &&\r
- (PathForReturn != NULL) &&\r
- (PathForReturn[PathSize - 1] != L'\\') &&\r
- (AlignedNode->PathName[0] != L'\\')) {\r
- PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);\r
- }\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // append the path part onto the filepath.\r
+ //\r
+ ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
+\r
+ AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
+ if (AlignedNode == NULL) {\r
+ FreePool (PathForReturn);\r
+ return NULL;\r
+ }\r
\r
- PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
- FreePool(AlignedNode);\r
+ // File Path Device Path Nodes 'can optionally add a "\" separator to\r
+ // the beginning and/or the end of the Path Name string.'\r
+ // (UEFI Spec 2.4 section 9.3.6.4).\r
+ // If necessary, add a "\", but otherwise don't\r
+ // (This is specified in the above section, and also implied by the\r
+ // UEFI Shell spec section 3.7)\r
+ if ((PathSize != 0) &&\r
+ (PathForReturn != NULL) &&\r
+ (PathForReturn[PathSize / sizeof (CHAR16) - 1] != L'\\') &&\r
+ (AlignedNode->PathName[0] != L'\\')) {\r
+ PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);\r
}\r
+\r
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
+ FreePool(AlignedNode);\r
} // for loop of remaining nodes\r
}\r
if (PathForReturn != NULL) {\r
//\r
// build the full device path\r
//\r
- if (*(Path+StrLen(MapName)+1) == CHAR_NULL) {\r
+ if ((*(Path+StrLen(MapName)) != CHAR_NULL) &&\r
+ (*(Path+StrLen(MapName)+1) == CHAR_NULL)) {\r
DevicePathForReturn = FileDevicePath(Handle, L"\\");\r
} else {\r
DevicePathForReturn = FileDevicePath(Handle, Path+StrLen(MapName));\r
@retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory\r
could not be opened.\r
@retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.\r
- @retval EFI_DEVICE_ERROR The device had an error\r
+ @retval EFI_DEVICE_ERROR The device had an error.\r
+ @retval Others Error status returned from EFI_SIMPLE_FILE_SYSTEM_PROTOCOL->OpenVolume().\r
**/\r
EFI_STATUS\r
EFIAPI\r
// Open the root volume now...\r
//\r
Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &RealFileHandle);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
*FileHandle = ConvertEfiFileProtocolToShellHandle(RealFileHandle, EfiShellGetMapFromDevicePath(&DevPath));\r
- return (Status);\r
+ return (EFI_SUCCESS);\r
}\r
\r
/**\r
@param Attributes the File Attributes to use when creating a new file.\r
\r
@retval EFI_SUCCESS the file is open and FileHandle is valid\r
- @retval EFI_UNSUPPORTED the device path cotained non-path elements\r
- @retval other an error ocurred.\r
+ @retval EFI_UNSUPPORTED the device path contained non-path elements\r
+ @retval other an error occurred.\r
**/\r
EFI_STATUS\r
-EFIAPI\r
InternalOpenFileDevicePath(\r
IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
OUT SHELL_FILE_HANDLE *FileHandle,\r
Handle1 = ConvertShellHandleToEfiFileProtocol(ShellHandle);\r
if (Handle1 != NULL) {\r
//\r
- // chop off the begining part before the file system part...\r
+ // chop off the beginning part before the file system part...\r
//\r
///@todo BlockIo?\r
Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,\r
already exists and is non-volatile then EFI_INVALID_PARAMETER is returned.\r
\r
@param FileName Pointer to NULL-terminated file path\r
- @param FileAttribs The new file's attrbiutes. the different attributes are\r
+ @param FileAttribs The new file's attributes. the different attributes are\r
described in EFI_FILE_PROTOCOL.Open().\r
@param FileHandle On return, points to the created file handle or directory's handle\r
\r
@retval EFI_SUCCESS The file was opened. FileHandle points to the new file's handle.\r
@retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
@retval EFI_UNSUPPORTED could not open the file path\r
- @retval EFI_NOT_FOUND the specified file could not be found on the devide, or could not\r
+ @retval EFI_NOT_FOUND the specified file could not be found on the device, or could not\r
file the file system on the device.\r
@retval EFI_NO_MEDIA the device has no medium.\r
@retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no\r
{\r
EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
EFI_STATUS Status;\r
+ BOOLEAN Volatile;\r
\r
//\r
// Is this for an environment variable\r
// do we start with >v\r
//\r
if (StrStr(FileName, L">v") == FileName) {\r
- if (!IsVolatileEnv(FileName+2)) {\r
+ Status = IsVolatileEnv (FileName + 2, &Volatile);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (!Volatile) {\r
return (EFI_INVALID_PARAMETER);\r
}\r
*FileHandle = CreateFileInterfaceEnv(FileName+2);\r
@retval EFI_ACCESS_DENIED Guid already is assigned a name.\r
**/\r
EFI_STATUS\r
-EFIAPI \r
+EFIAPI\r
EfiShellRegisterGuidName(\r
IN CONST EFI_GUID *Guid,\r
IN CONST CHAR16 *GuidName\r
{\r
EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
EFI_STATUS Status;\r
+ BOOLEAN Volatile;\r
\r
*FileHandle = NULL;\r
\r
}\r
\r
//\r
- // Is this for NUL file\r
+ // Is this for NUL / NULL file\r
//\r
- if (StrCmp(FileName, L"NUL") == 0) {\r
+ if ((gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)FileName, L"NUL") == 0) ||\r
+ (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)FileName, L"NULL") == 0)) {\r
*FileHandle = &FileInterfaceNulFile;\r
return (EFI_SUCCESS);\r
}\r
// do we start with >v\r
//\r
if (StrStr(FileName, L">v") == FileName) {\r
- if (!IsVolatileEnv(FileName+2) &&\r
+ Status = IsVolatileEnv (FileName + 2, &Volatile);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if (!Volatile &&\r
((OpenMode & EFI_FILE_MODE_WRITE) != 0)) {\r
return (EFI_INVALID_PARAMETER);\r
}\r
// We are opening a regular file.\r
//\r
DevicePath = EfiShellGetDevicePathFromFilePath(FileName);\r
-// DEBUG_CODE(InternalShellProtocolDebugPrintMessage (NULL, DevicePath););\r
+\r
if (DevicePath == NULL) {\r
return (EFI_NOT_FOUND);\r
}\r
//\r
// now delete the file\r
//\r
+ ShellFileHandleRemove(FileHandle);\r
return (ShellInfoObject.NewEfiShellProtocol->DeleteFile(FileHandle));\r
}\r
\r
variables with the format 'x=y', where x is the\r
environment variable name and y is the value. If this\r
is NULL, then the current shell environment is used.\r
- \r
+\r
@param[out] StartImageStatus Returned status from gBS->StartImage.\r
\r
@retval EFI_SUCCESS The command executed successfully. The status code\r
@retval EFI_UNSUPPORTED Nested shell invocations are not allowed.\r
**/\r
EFI_STATUS\r
-EFIAPI\r
InternalShellExecuteDevicePath(\r
IN CONST EFI_HANDLE *ParentImageHandle,\r
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
}\r
\r
InitializeListHead(&OrigEnvs);\r
+ ZeroMem(&ShellParamsProtocol, sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
\r
NewHandle = NULL;\r
- \r
+\r
NewCmdLine = AllocateCopyPool (StrSize (CommandLine), CommandLine);\r
if (NewCmdLine == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
if (NewHandle != NULL) {\r
gBS->UnloadImage(NewHandle);\r
}\r
+ FreePool (NewCmdLine);\r
return (Status);\r
}\r
Status = gBS->OpenProtocol(\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
\r
if (!EFI_ERROR(Status)) {\r
+ //\r
+ // If the image is not an app abort it.\r
+ //\r
+ if (LoadedImage->ImageCodeType != EfiLoaderCode){\r
+ ShellPrintHiiEx(\r
+ -1,\r
+ -1,\r
+ NULL,\r
+ STRING_TOKEN (STR_SHELL_IMAGE_NOT_APP),\r
+ ShellInfoObject.HiiHandle\r
+ );\r
+ goto UnloadImage;\r
+ }\r
+\r
ASSERT(LoadedImage->LoadOptionsSize == 0);\r
if (NewCmdLine != NULL) {\r
LoadedImage->LoadOptionsSize = (UINT32)StrSize(NewCmdLine);\r
ShellParamsProtocol.StdIn = ShellInfoObject.NewShellParametersProtocol->StdIn;\r
ShellParamsProtocol.StdOut = ShellInfoObject.NewShellParametersProtocol->StdOut;\r
ShellParamsProtocol.StdErr = ShellInfoObject.NewShellParametersProtocol->StdErr;\r
- Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, NULL, NULL);\r
- ASSERT_EFI_ERROR(Status);\r
+ Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, Efi_Application, NULL, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ goto UnloadImage;\r
+ }\r
+\r
//\r
// Replace Argv[0] with the full path of the binary we're executing:\r
// If the command line was "foo", the binary might be called "foo.efi".\r
\r
return(Status);\r
}\r
+\r
+/**\r
+ internal worker function to load and run an image in the current shell.\r
+\r
+ @param CommandLine Points to the NULL-terminated UCS-2 encoded string\r
+ containing the command line. If NULL then the command-\r
+ line will be empty.\r
+ @param Environment Points to a NULL-terminated array of environment\r
+ variables with the format 'x=y', where x is the\r
+ environment variable name and y is the value. If this\r
+ is NULL, then the current shell environment is used.\r
+\r
+ @param[out] StartImageStatus Returned status from the command line.\r
+\r
+ @retval EFI_SUCCESS The command executed successfully. The status code\r
+ returned by the command is pointed to by StatusCode.\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES Out of resources.\r
+ @retval EFI_UNSUPPORTED Nested shell invocations are not allowed.\r
+**/\r
+EFI_STATUS\r
+InternalShellExecute(\r
+ IN CONST CHAR16 *CommandLine OPTIONAL,\r
+ IN CONST CHAR16 **Environment OPTIONAL,\r
+ OUT EFI_STATUS *StartImageStatus OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS CleanupStatus;\r
+ LIST_ENTRY OrigEnvs;\r
+\r
+ InitializeListHead(&OrigEnvs);\r
+\r
+ //\r
+ // Save our current environment settings for later restoration if necessary\r
+ //\r
+ if (Environment != NULL) {\r
+ Status = GetEnvironmentVariableList(&OrigEnvs);\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = SetEnvironmentVariables(Environment);\r
+ } else {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ Status = RunShellCommand(CommandLine, StartImageStatus);\r
+\r
+ // Restore environment variables\r
+ if (!IsListEmpty(&OrigEnvs)) {\r
+ CleanupStatus = SetEnvironmentVariableList(&OrigEnvs);\r
+ ASSERT_EFI_ERROR (CleanupStatus);\r
+ }\r
+\r
+ return(Status);\r
+}\r
+\r
+/**\r
+ Determine if the UEFI Shell is currently running with nesting enabled or disabled.\r
+\r
+ @retval FALSE nesting is required\r
+ @retval other nesting is enabled\r
+**/\r
+STATIC\r
+BOOLEAN\r
+NestingEnabled(\r
+ VOID\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *Temp;\r
+ CHAR16 *Temp2;\r
+ UINTN TempSize;\r
+ BOOLEAN RetVal;\r
+\r
+ RetVal = TRUE;\r
+ Temp = NULL;\r
+ Temp2 = NULL;\r
+\r
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {\r
+ TempSize = 0;\r
+ Temp = NULL;\r
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ Temp = AllocateZeroPool(TempSize + sizeof(CHAR16));\r
+ if (Temp != NULL) {\r
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);\r
+ }\r
+ }\r
+ Temp2 = StrnCatGrow(&Temp2, NULL, mNoNestingTrue, 0);\r
+ if (Temp != NULL && Temp2 != NULL && StringNoCaseCompare(&Temp, &Temp2) == 0) {\r
+ //\r
+ // Use the no nesting method.\r
+ //\r
+ RetVal = FALSE;\r
+ }\r
+ }\r
+\r
+ SHELL_FREE_NON_NULL(Temp);\r
+ SHELL_FREE_NON_NULL(Temp2);\r
+ return (RetVal);\r
+}\r
+\r
/**\r
Execute the command line.\r
\r
variables with the format 'x=y', where x is the\r
environment variable name and y is the value. If this\r
is NULL, then the current shell environment is used.\r
- @param StatusCode Points to the status code returned by the command.\r
+ @param StatusCode Points to the status code returned by the CommandLine.\r
\r
@retval EFI_SUCCESS The command executed successfully. The status code\r
returned by the command is pointed to by StatusCode.\r
CHAR16 *Temp;\r
EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
UINTN Size;\r
- EFI_STATUS CalleeStatusCode;\r
\r
- CalleeStatusCode = EFI_SUCCESS;\r
- \r
if ((PcdGet8(PcdShellSupportLevel) < 1)) {\r
return (EFI_UNSUPPORTED);\r
}\r
\r
- if (Environment != NULL) {\r
- // If Environment isn't null, load a new image of the shell with its own\r
- // environment\r
+ if (NestingEnabled()) {\r
DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
- \r
+\r
DEBUG_CODE_BEGIN();\r
Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
FreePool(Temp);\r
Temp = NULL;\r
Size = 0;\r
ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));\r
- StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);\r
+ StrnCatGrow(&Temp, &Size, L"Shell.efi -exit ", 0);\r
StrnCatGrow(&Temp, &Size, CommandLine, 0);\r
\r
Status = InternalShellExecuteDevicePath(\r
FreePool(DevPath);\r
FreePool(Temp);\r
} else {\r
- // If Environment is NULL, we are free to use and mutate the current shell\r
- // environment. This is much faster as uses much less memory.\r
-\r
- if (CommandLine == NULL) {\r
- CommandLine = L"";\r
- }\r
-\r
- Status = RunShellCommand (CommandLine, &CalleeStatusCode);\r
-\r
- // Pass up the command's exit code if the caller wants it\r
- if (StatusCode != NULL) {\r
- *StatusCode = (EFI_STATUS) CalleeStatusCode;\r
- }\r
+ Status = InternalShellExecute(\r
+ (CONST CHAR16*)CommandLine,\r
+ (CONST CHAR16**)Environment,\r
+ StatusCode);\r
}\r
\r
return(Status);\r
@param FileListNode pointer to the list node to free\r
**/\r
VOID\r
-EFIAPI\r
InternalFreeShellFileInfoNode(\r
IN EFI_SHELL_FILE_INFO *FileListNode\r
)\r
@param[in] Node The node to copy from.\r
@param[in] Save TRUE to set Node->Handle to NULL, FALSE otherwise.\r
\r
- @retval NULL a memory allocation error ocurred\r
+ @retval NULL a memory allocation error occurred\r
@return != NULL a pointer to the new node\r
**/\r
EFI_SHELL_FILE_INFO*\r
-EFIAPI\r
InternalDuplicateShellFileInfo(\r
IN EFI_SHELL_FILE_INFO *Node,\r
IN BOOLEAN Save\r
@param[in] Handle Handle member initial value.\r
@param[in] Info Info struct to copy.\r
\r
- @retval NULL An error ocurred.\r
+ @retval NULL An error occurred.\r
@return a pointer to the newly allocated structure.\r
**/\r
EFI_SHELL_FILE_INFO *\r
-EFIAPI\r
CreateAndPopulateShellFileInfo(\r
IN CONST CHAR16 *BasePath,\r
IN CONST EFI_STATUS Status,\r
; !EFI_ERROR(Status) && !NoFile\r
; Status = FileHandleFindNextFile(FileDirHandle, FileInfo, &NoFile)\r
){\r
+ if (ShellFileList == NULL) {\r
+ ShellFileList = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
+ if (ShellFileList == NULL) {\r
+ SHELL_FREE_NON_NULL (BasePath);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ InitializeListHead(&ShellFileList->Link);\r
+ }\r
//\r
// allocate a new EFI_SHELL_FILE_INFO and populate it...\r
//\r
ShellFileListItem = CreateAndPopulateShellFileInfo(\r
BasePath,\r
- EFI_SUCCESS, // success since we didnt fail to open it...\r
+ EFI_SUCCESS, // success since we didn't fail to open it...\r
FileInfo->FileName,\r
NULL, // no handle since not open\r
FileInfo);\r
-\r
- if (ShellFileList == NULL) {\r
- ShellFileList = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
- ASSERT(ShellFileList != NULL);\r
- InitializeListHead(&ShellFileList->Link);\r
+ if (ShellFileListItem == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ //\r
+ // Free resources outside the loop.\r
+ //\r
+ break;\r
}\r
InsertTailList(&ShellFileList->Link, &ShellFileListItem->Link);\r
}\r
@retval EFI_NOT_FOUND GuidName is not a known GUID Name.\r
**/\r
EFI_STATUS\r
-EFIAPI \r
+EFIAPI\r
EfiShellGetGuidFromName(\r
IN CONST CHAR16 *GuidName,\r
OUT EFI_GUID *Guid\r
if (Guid == NULL || GuidName == NULL) {\r
return (EFI_INVALID_PARAMETER);\r
}\r
- \r
+\r
Status = GetGuidFromStringName(GuidName, NULL, &NewGuid);\r
\r
if (!EFI_ERROR(Status)) {\r
- CopyGuid(NewGuid, Guid);\r
+ CopyGuid(Guid, NewGuid);\r
}\r
\r
return (Status);\r
@retval EFI_NOT_FOUND Guid is not assigned a name.\r
**/\r
EFI_STATUS\r
-EFIAPI \r
+EFIAPI\r
EfiShellGetGuidName(\r
IN CONST EFI_GUID *Guid,\r
OUT CONST CHAR16 **GuidName\r
return (EFI_SUCCESS);\r
}\r
\r
-/**\r
- Updates a file name to be preceeded by the mapped drive name\r
-\r
- @param[in] BasePath the Mapped drive name to prepend\r
- @param[in, out] Path pointer to pointer to the file name to update.\r
-\r
- @retval EFI_SUCCESS\r
- @retval EFI_OUT_OF_RESOURCES\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-UpdateFileName(\r
- IN CONST CHAR16 *BasePath,\r
- IN OUT CHAR16 **Path\r
- )\r
-{\r
- CHAR16 *Path2;\r
- UINTN Path2Size;\r
-\r
- Path2Size = 0;\r
- Path2 = NULL;\r
-\r
- ASSERT(Path != NULL);\r
- ASSERT(*Path != NULL);\r
- ASSERT(BasePath != NULL);\r
-\r
- //\r
- // convert a local path to an absolute path\r
- //\r
- if (StrStr(*Path, L":") == NULL) {\r
- ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));\r
- StrnCatGrow(&Path2, &Path2Size, BasePath, 0);\r
- if (Path2 == NULL) {\r
- return (EFI_OUT_OF_RESOURCES);\r
- }\r
- ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));\r
- StrnCatGrow(&Path2, &Path2Size, (*Path)[0] == L'\\'?(*Path) + 1 :*Path, 0);\r
- if (Path2 == NULL) {\r
- return (EFI_OUT_OF_RESOURCES);\r
- }\r
- }\r
-\r
- FreePool(*Path);\r
- (*Path) = Path2;\r
\r
- return (EFI_SUCCESS);\r
-}\r
\r
/**\r
If FileHandle is a directory then the function reads from FileHandle and reads in\r
@retval EFI_OUT_OF_RESOURCES a memory allocation failed\r
**/\r
EFI_STATUS\r
-EFIAPI\r
ShellSearchHandle(\r
IN CONST CHAR16 *FilePattern,\r
IN EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation,\r
; NextFilePatternStart++);\r
\r
CurrentFilePattern = AllocateZeroPool((NextFilePatternStart-FilePattern+1)*sizeof(CHAR16));\r
- ASSERT(CurrentFilePattern != NULL);\r
+ if (CurrentFilePattern == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
StrnCpyS(CurrentFilePattern, NextFilePatternStart-FilePattern+1, FilePattern, NextFilePatternStart-FilePattern);\r
\r
if (CurrentFilePattern[0] == CHAR_NULL\r
){\r
if (UnicodeCollation->MetaiMatch(UnicodeCollation, (CHAR16*)ShellInfoNode->FileName, CurrentFilePattern)){\r
if (ShellInfoNode->FullName != NULL && StrStr(ShellInfoNode->FullName, L":") == NULL) {\r
- Size = StrSize(ShellInfoNode->FullName);\r
- Size += StrSize(MapName) + sizeof(CHAR16);\r
+ Size = StrSize (ShellInfoNode->FullName) + StrSize (MapName);\r
NewFullName = AllocateZeroPool(Size);\r
if (NewFullName == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
} else {\r
- StrCpyS(NewFullName, Size/sizeof(CHAR16), MapName);\r
- StrCatS(NewFullName, Size/sizeof(CHAR16), ShellInfoNode->FullName+1);\r
- FreePool((VOID*)ShellInfoNode->FullName);\r
+ StrCpyS(NewFullName, Size / sizeof(CHAR16), MapName);\r
+ StrCatS(NewFullName, Size / sizeof(CHAR16), ShellInfoNode->FullName);\r
+ FreePool ((VOID *) ShellInfoNode->FullName);\r
ShellInfoNode->FullName = NewFullName;\r
}\r
}\r
// recurse with the next part of the pattern\r
//\r
Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode, MapName);\r
+ EfiShellClose(ShellInfoNode->Handle);\r
+ ShellInfoNode->Handle = NULL;\r
}\r
} else if (!EFI_ERROR(Status)) {\r
//\r
// copy the information we need into a new Node\r
//\r
NewShellNode = InternalDuplicateShellFileInfo(ShellInfoNode, FALSE);\r
- ASSERT(NewShellNode != NULL);\r
if (NewShellNode == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
}\r
}\r
}\r
\r
+ if (*FileList == NULL || (*FileList != NULL && IsListEmpty(&(*FileList)->Link))) {\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+\r
FreePool(CurrentFilePattern);\r
return (Status);\r
}\r
\r
PatternCopy = PathCleanUpDirectories(PatternCopy);\r
\r
- Count = StrStr(PatternCopy, L":") - PatternCopy;\r
- Count += 2;\r
+ Count = StrStr(PatternCopy, L":") - PatternCopy + 1;\r
+ ASSERT (Count <= StrLen (PatternCopy));\r
\r
ASSERT(MapName == NULL);\r
MapName = StrnCatGrow(&MapName, NULL, PatternCopy, Count);\r
; PatternCurrentLocation++);\r
PatternCurrentLocation++;\r
Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL, MapName);\r
+ EfiShellClose(RootFileHandle);\r
}\r
FreePool(RootDevicePath);\r
}\r
pointer does not need to be freed by the caller.\r
**/\r
CONST CHAR16 *\r
-EFIAPI \r
+EFIAPI\r
EfiShellGetEnvEx(\r
IN CONST CHAR16 *Name,\r
OUT UINT32 *Attributes OPTIONAL\r
EFI_STATUS Status;\r
VOID *Buffer;\r
UINTN Size;\r
- LIST_ENTRY List;\r
ENV_VAR_LIST *Node;\r
CHAR16 *CurrentWriteLocation;\r
\r
Buffer = NULL;\r
\r
if (Name == NULL) {\r
- //\r
- // Get all our environment variables\r
- //\r
- InitializeListHead(&List);\r
- Status = GetEnvironmentVariableList(&List);\r
- if (EFI_ERROR(Status)){\r
- return (NULL);\r
- }\r
\r
//\r
// Build the semi-colon delimited list. (2 passes)\r
//\r
- for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List)\r
- ; !IsNull(&List, &Node->Link)\r
- ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link)\r
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)\r
+ ; !IsNull(&gShellEnvVarList.Link, &Node->Link)\r
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)\r
){\r
ASSERT(Node->Key != NULL);\r
Size += StrSize(Node->Key);\r
\r
Buffer = AllocateZeroPool(Size);\r
if (Buffer == NULL) {\r
- if (!IsListEmpty (&List)) {\r
- FreeEnvironmentVariableList(&List);\r
- }\r
return (NULL);\r
}\r
CurrentWriteLocation = (CHAR16*)Buffer;\r
\r
- for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List)\r
- ; !IsNull(&List, &Node->Link)\r
- ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link)\r
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)\r
+ ; !IsNull(&gShellEnvVarList.Link, &Node->Link)\r
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)\r
){\r
ASSERT(Node->Key != NULL);\r
- StrCpyS( CurrentWriteLocation, \r
- (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)), \r
+ StrCpyS( CurrentWriteLocation,\r
+ (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)),\r
Node->Key\r
);\r
CurrentWriteLocation += StrLen(CurrentWriteLocation) + 1;\r
}\r
\r
- //\r
- // Free the list...\r
- //\r
- if (!IsListEmpty (&List)) {\r
- FreeEnvironmentVariableList(&List);\r
- }\r
} else {\r
//\r
// We are doing a specific environment variable\r
//\r
+ Status = ShellFindEnvVarInList(Name, (CHAR16**)&Buffer, &Size, Attributes);\r
\r
- //\r
- // get the size we need for this EnvVariable\r
- //\r
- Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ if (EFI_ERROR(Status)){\r
//\r
- // Allocate the space and recall the get function\r
+ // get the size we need for this EnvVariable\r
//\r
- Buffer = AllocateZeroPool(Size);\r
Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);\r
- }\r
- //\r
- // we didnt get it (might not exist)\r
- // free the memory if we allocated any and return NULL\r
- //\r
- if (EFI_ERROR(Status)) {\r
- if (Buffer != NULL) {\r
- FreePool(Buffer);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ //\r
+ // Allocate the space and recall the get function\r
+ //\r
+ Buffer = AllocateZeroPool(Size);\r
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);\r
+ }\r
+ //\r
+ // we didn't get it (might not exist)\r
+ // free the memory if we allocated any and return NULL\r
+ //\r
+ if (EFI_ERROR(Status)) {\r
+ if (Buffer != NULL) {\r
+ FreePool(Buffer);\r
+ }\r
+ return (NULL);\r
+ } else {\r
+ //\r
+ // If we did not find the environment variable in the gShellEnvVarList\r
+ // but get it from UEFI variable storage successfully then we need update\r
+ // the gShellEnvVarList.\r
+ //\r
+ ShellFreeEnvVarList ();\r
+ Status = ShellInitEnvVarList ();\r
+ ASSERT (Status == EFI_SUCCESS);\r
}\r
- return (NULL);\r
}\r
}\r
\r
@retval EFI_SUCCESS The environment variable was successfully updated.\r
**/\r
EFI_STATUS\r
-EFIAPI\r
InternalEfiShellSetEnv(\r
IN CONST CHAR16 *Name,\r
IN CONST CHAR16 *Value,\r
IN BOOLEAN Volatile\r
)\r
{\r
+ EFI_STATUS Status;\r
+\r
if (Value == NULL || StrLen(Value) == 0) {\r
- return (SHELL_DELETE_ENVIRONMENT_VARIABLE(Name));\r
+ Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Name);\r
+ if (!EFI_ERROR(Status)) {\r
+ ShellRemvoeEnvVarFromList(Name);\r
+ }\r
} else {\r
SHELL_DELETE_ENVIRONMENT_VARIABLE(Name);\r
- if (Volatile) {\r
- return (SHELL_SET_ENVIRONMENT_VARIABLE_V(Name, StrSize(Value), Value));\r
- } else {\r
- return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(Name, StrSize(Value), Value));\r
+ Status = ShellAddEnvVarToList(\r
+ Name, Value, StrSize(Value),\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | (Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE)\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = Volatile\r
+ ? SHELL_SET_ENVIRONMENT_VARIABLE_V (Name, StrSize (Value) - sizeof (CHAR16), Value)\r
+ : SHELL_SET_ENVIRONMENT_VARIABLE_NV (Name, StrSize (Value) - sizeof (CHAR16), Value);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellRemvoeEnvVarFromList(Name);\r
+ }\r
}\r
}\r
+ return Status;\r
}\r
\r
/**\r
//\r
// Make sure we dont 'set' a predefined read only variable\r
//\r
- if (gUnicodeCollation->StriColl(\r
- gUnicodeCollation,\r
- (CHAR16*)Name,\r
- L"cwd") == 0\r
- ||gUnicodeCollation->StriColl(\r
- gUnicodeCollation,\r
- (CHAR16*)Name,\r
- L"Lasterror") == 0\r
- ||gUnicodeCollation->StriColl(\r
- gUnicodeCollation,\r
- (CHAR16*)Name,\r
- L"profiles") == 0\r
- ||gUnicodeCollation->StriColl(\r
- gUnicodeCollation,\r
- (CHAR16*)Name,\r
- L"uefishellsupport") == 0\r
- ||gUnicodeCollation->StriColl(\r
- gUnicodeCollation,\r
- (CHAR16*)Name,\r
- L"uefishellversion") == 0\r
- ||gUnicodeCollation->StriColl(\r
- gUnicodeCollation,\r
- (CHAR16*)Name,\r
- L"uefiversion") == 0\r
- ){\r
+ if ((StrCmp (Name, L"cwd") == 0) ||\r
+ (StrCmp (Name, L"lasterror") == 0) ||\r
+ (StrCmp (Name, L"profiles") == 0) ||\r
+ (StrCmp (Name, L"uefishellsupport") == 0) ||\r
+ (StrCmp (Name, L"uefishellversion") == 0) ||\r
+ (StrCmp (Name, L"uefiversion") == 0) ||\r
+ (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest &&\r
+ StrCmp (Name, mNoNestingEnvVarName) == 0)\r
+ ) {\r
return (EFI_INVALID_PARAMETER);\r
}\r
return (InternalEfiShellSetEnv(Name, Value, Volatile));\r
FileSystemMapping is not NULL, it returns the current directory associated with the\r
FileSystemMapping. In both cases, the returned name includes the file system\r
mapping (i.e. fs0:\current-dir).\r
- \r
+\r
Note that the current directory string should exclude the tailing backslash character.\r
\r
@param FileSystemMapping A pointer to the file system mapping. If NULL,\r
directory is changed.\r
@param Dir Points to the NULL-terminated directory on the device specified by FileSystem.\r
\r
- @retval EFI_SUCCESS The operation was sucessful\r
+ @retval EFI_SUCCESS The operation was successful\r
@retval EFI_NOT_FOUND The file system could not be found\r
**/\r
EFI_STATUS\r
// make that the current file system mapping\r
//\r
if (MapListItem != NULL) {\r
- gShellCurDir = MapListItem;\r
+ gShellCurMapping = MapListItem;\r
}\r
} else {\r
- MapListItem = gShellCurDir;\r
+ MapListItem = gShellCurMapping;\r
}\r
\r
if (MapListItem == NULL) {\r
+ FreePool (DirectoryName);\r
+ SHELL_FREE_NON_NULL(MapName);\r
return (EFI_NOT_FOUND);\r
}\r
\r
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName+StrLen(MapName), 0);\r
}\r
+ FreePool (MapName);\r
} else {\r
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0);\r
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
if (MapListItem->CurrentDirectoryPath != NULL) {\r
MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;\r
- }\r
+ }\r
}\r
} else {\r
//\r
// cant have a mapping in the directory...\r
//\r
if (StrStr(DirectoryName, L":") != NULL) {\r
+ FreePool (DirectoryName);\r
return (EFI_INVALID_PARAMETER);\r
}\r
//\r
//\r
MapListItem = ShellCommandFindMapItem(FileSystem);\r
if (MapListItem == NULL) {\r
+ FreePool (DirectoryName);\r
return (EFI_INVALID_PARAMETER);\r
}\r
-// gShellCurDir = MapListItem;\r
+// gShellCurMapping = MapListItem;\r
if (DirectoryName != NULL) {\r
//\r
// change current dir on that file system\r
}\r
}\r
}\r
+ FreePool (DirectoryName);\r
//\r
// if updated the current directory then update the environment variable\r
//\r
- if (MapListItem == gShellCurDir) {\r
+ if (MapListItem == gShellCurMapping) {\r
Size = 0;\r
ASSERT((TempString == NULL && Size == 0) || (TempString != NULL));\r
StrnCatGrow(&TempString, &Size, MapListItem->MapName, 0);\r
&& (Command[StrLen(Command)-4] == L'.')\r
) {\r
FixCommand = AllocateZeroPool(StrSize(Command) - 4 * sizeof (CHAR16));\r
- ASSERT(FixCommand != NULL);\r
+ if (FixCommand == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- StrnCpyS( FixCommand, \r
- (StrSize(Command) - 4 * sizeof (CHAR16))/sizeof(CHAR16), \r
- Command, \r
+ StrnCpyS( FixCommand,\r
+ (StrSize(Command) - 4 * sizeof (CHAR16))/sizeof(CHAR16),\r
+ Command,\r
StrLen(Command)-4\r
);\r
Status = ProcessManFile(FixCommand, FixCommand, Sections, NULL, HelpText);\r
}\r
\r
/**\r
- function to return a semi-colon delimeted list of all alias' in the current shell\r
+ function to return a semi-colon delimited list of all alias' in the current shell\r
\r
up to caller to free the memory.\r
\r
@retval NULL No alias' were found\r
- @retval NULL An error ocurred getting alias'\r
+ @retval NULL An error occurred getting alias'\r
@return !NULL a list of all alias'\r
**/\r
CHAR16 *\r
-EFIAPI\r
InternalEfiShellGetListAlias(\r
+ VOID\r
)\r
{\r
- \r
+\r
EFI_STATUS Status;\r
EFI_GUID Guid;\r
CHAR16 *VariableName;\r
RetVal = NULL;\r
break;\r
}\r
- \r
+\r
NameSize = NameBufferSize;\r
Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);\r
}\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
SHELL_FREE_NON_NULL(RetVal);\r
RetVal = NULL;\r
break;\r
}\r
- \r
+\r
if (CompareGuid(&Guid, &gShellAliasGuid)){\r
ASSERT((RetVal == NULL && RetSize == 0) || (RetVal != NULL));\r
RetVal = StrnCatGrow(&RetVal, &RetSize, VariableName, 0);\r
/**\r
Convert a null-terminated unicode string, in-place, to all lowercase.\r
Then return it.\r
- \r
+\r
@param Str The null-terminated string to be converted to all lowercase.\r
- \r
- @return The null-terminated string converted into all lowercase. \r
+\r
+ @return The null-terminated string converted into all lowercase.\r
**/\r
CHAR16 *\r
ToLower (\r
@param[out] Volatile upon return of a single command if TRUE indicates\r
this is stored in a volatile fashion. FALSE otherwise.\r
\r
- @return If Alias is not NULL, it will return a pointer to\r
+ @return If Alias is not NULL, it will return a pointer to\r
the NULL-terminated command for that alias.\r
If Alias is NULL, ReturnedData points to a ';'\r
delimited list of alias (e.g.\r
ReturnedData = "dir;del;copy;mfp") that is NULL-terminated.\r
- @retval NULL an error ocurred\r
+ @retval NULL an error occurred\r
@retval NULL Alias was not a valid Alias\r
**/\r
CONST CHAR16 *\r
// Convert to lowercase to make aliases case-insensitive\r
if (Alias != NULL) {\r
AliasLower = AllocateCopyPool (StrSize (Alias), Alias);\r
- ASSERT (AliasLower != NULL);\r
+ if (AliasLower == NULL) {\r
+ return NULL;\r
+ }\r
ToLower (AliasLower);\r
\r
if (Volatile == NULL) {\r
GetVariable2 (AliasLower, &gShellAliasGuid, (VOID **)&AliasVal, NULL);\r
+ FreePool(AliasLower);\r
return (AddBufferToFreeList(AliasVal));\r
}\r
RetSize = 0;\r
if (RetVal != NULL) {\r
FreePool(RetVal);\r
}\r
+ FreePool(AliasLower);\r
return (NULL);\r
}\r
if ((EFI_VARIABLE_NON_VOLATILE & Attribs) == EFI_VARIABLE_NON_VOLATILE) {\r
@retval EFI_NOT_FOUND the Alias intended to be deleted was not found\r
**/\r
EFI_STATUS\r
-EFIAPI\r
InternalSetAlias(\r
IN CONST CHAR16 *Command,\r
IN CONST CHAR16 *Alias,\r
{\r
EFI_STATUS Status;\r
CHAR16 *AliasLower;\r
+ BOOLEAN DeleteAlias;\r
\r
- // Convert to lowercase to make aliases case-insensitive\r
- if (Alias != NULL) {\r
- AliasLower = AllocateCopyPool (StrSize (Alias), Alias);\r
- ASSERT (AliasLower != NULL);\r
- ToLower (AliasLower);\r
- } else {\r
- AliasLower = NULL;\r
- }\r
-\r
- //\r
- // We must be trying to remove one if Alias is NULL\r
- //\r
+ DeleteAlias = FALSE;\r
if (Alias == NULL) {\r
//\r
+ // We must be trying to remove one if Alias is NULL\r
// remove an alias (but passed in COMMAND parameter)\r
//\r
- Status = (gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL));\r
- } else {\r
- //\r
- // Add and replace are the same\r
- //\r
-\r
- // We dont check the error return on purpose since the variable may not exist.\r
- gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL);\r
+ Alias = Command;\r
+ DeleteAlias = TRUE;\r
+ }\r
+ ASSERT (Alias != NULL);\r
\r
- Status = (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command));\r
+ //\r
+ // Convert to lowercase to make aliases case-insensitive\r
+ //\r
+ AliasLower = AllocateCopyPool (StrSize (Alias), Alias);\r
+ if (AliasLower == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
+ ToLower (AliasLower);\r
\r
- if (Alias != NULL) {\r
- FreePool (AliasLower);\r
+ if (DeleteAlias) {\r
+ Status = gRT->SetVariable (AliasLower, &gShellAliasGuid, 0, 0, NULL);\r
+ } else {\r
+ Status = gRT->SetVariable (\r
+ AliasLower, &gShellAliasGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | (Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE),\r
+ StrSize (Command), (VOID *) Command\r
+ );\r
}\r
+\r
+ FreePool (AliasLower);\r
+\r
return Status;\r
}\r
\r
@return An error from LocateHandle, CreateEvent, or other core function.\r
**/\r
EFI_STATUS\r
-EFIAPI\r
CreatePopulateInstallShellProtocol (\r
IN OUT EFI_SHELL_PROTOCOL **NewShell\r
)\r
EFI_HANDLE *Buffer;\r
UINTN HandleCounter;\r
SHELL_PROTOCOL_HANDLE_LIST *OldProtocolNode;\r
+ EFI_SHELL_PROTOCOL *OldShell;\r
\r
if (NewShell == NULL) {\r
return (EFI_INVALID_PARAMETER);\r
// now overwrite each of them, but save the info to restore when we end.\r
//\r
for (HandleCounter = 0 ; HandleCounter < (BufferSize/sizeof(EFI_HANDLE)) ; HandleCounter++) {\r
- OldProtocolNode = AllocateZeroPool(sizeof(SHELL_PROTOCOL_HANDLE_LIST));\r
- ASSERT(OldProtocolNode != NULL);\r
Status = gBS->OpenProtocol(Buffer[HandleCounter],\r
&gEfiShellProtocolGuid,\r
- (VOID **) &(OldProtocolNode->Interface),\r
+ (VOID **) &OldShell,\r
gImageHandle,\r
NULL,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
if (!EFI_ERROR(Status)) {\r
+ OldProtocolNode = AllocateZeroPool(sizeof(SHELL_PROTOCOL_HANDLE_LIST));\r
+ if (OldProtocolNode == NULL) {\r
+ if (!IsListEmpty (&ShellInfoObject.OldShellList.Link)) {\r
+ CleanUpShellProtocol (&mShellProtocol);\r
+ }\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ break;\r
+ }\r
//\r
// reinstall over the old one...\r
//\r
- OldProtocolNode->Handle = Buffer[HandleCounter];\r
+ OldProtocolNode->Handle = Buffer[HandleCounter];\r
+ OldProtocolNode->Interface = OldShell;\r
Status = gBS->ReinstallProtocolInterface(\r
OldProtocolNode->Handle,\r
&gEfiShellProtocolGuid,\r
(VOID*)(&mShellProtocol));\r
if (!EFI_ERROR(Status)) {\r
//\r
- // we reinstalled sucessfully. log this so we can reverse it later.\r
+ // we reinstalled successfully. log this so we can reverse it later.\r
//\r
\r
//\r
@retval EFI_SUCCESS The operation was successful.\r
**/\r
EFI_STATUS\r
-EFIAPI\r
CleanUpShellProtocol (\r
IN OUT EFI_SHELL_PROTOCOL *NewShell\r
)\r
{\r
- EFI_STATUS Status;\r
SHELL_PROTOCOL_HANDLE_LIST *Node2;\r
- EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
\r
//\r
// if we need to restore old protocols...\r
//\r
if (!IsListEmpty(&ShellInfoObject.OldShellList.Link)) {\r
- for (Node2 = (SHELL_PROTOCOL_HANDLE_LIST *)GetFirstNode(&ShellInfoObject.OldShellList.Link)\r
+ for (Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link)\r
; !IsListEmpty (&ShellInfoObject.OldShellList.Link)\r
- ; Node2 = (SHELL_PROTOCOL_HANDLE_LIST *)GetFirstNode(&ShellInfoObject.OldShellList.Link)\r
- ){\r
- RemoveEntryList(&Node2->Link);\r
- Status = gBS->ReinstallProtocolInterface(Node2->Handle,\r
- &gEfiShellProtocolGuid,\r
- NewShell,\r
- Node2->Interface);\r
- FreePool(Node2);\r
+ ; Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link)\r
+ ) {\r
+ RemoveEntryList (&Node2->Link);\r
+ gBS->ReinstallProtocolInterface (Node2->Handle, &gEfiShellProtocolGuid, NewShell, Node2->Interface);\r
+ FreePool (Node2);\r
}\r
} else {\r
//\r
// no need to restore\r
//\r
- Status = gBS->UninstallProtocolInterface(gImageHandle,\r
- &gEfiShellProtocolGuid,\r
- NewShell);\r
+ gBS->UninstallProtocolInterface (gImageHandle, &gEfiShellProtocolGuid, NewShell);\r
}\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Cleanup the shell environment.\r
+\r
+ @param[in, out] NewShell The pointer to the new shell protocol structure.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+CleanUpShellEnvironment (\r
+ IN OUT EFI_SHELL_PROTOCOL *NewShell\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
+\r
+ CleanUpShellProtocol (NewShell);\r
+\r
Status = gBS->CloseEvent(NewShell->ExecutionBreak);\r
NewShell->ExecutionBreak = NULL;\r
\r
if ( ((KeyData->Key.UnicodeChar == L'c') &&\r
(KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))) ||\r
(KeyData->Key.UnicodeChar == 3)\r
- ){ \r
+ ){\r
if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {\r
return (EFI_UNSUPPORTED);\r
}\r
return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak));\r
} else if ((KeyData->Key.UnicodeChar == L's') &&\r
(KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))\r
- ){ \r
+ ){\r
ShellInfoObject.HaltOutput = TRUE;\r
}\r
return (EFI_SUCCESS);\r
}\r
\r
/**\r
- Function to start monitoring for CTRL-C using SimpleTextInputEx. This \r
+ Function to start monitoring for CTRL-C using SimpleTextInputEx. This\r
feature's enabled state was not known when the shell initially launched.\r
\r
@retval EFI_SUCCESS The feature is enabled.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory available.\r
**/\r
EFI_STATUS\r
-EFIAPI\r
InernalEfiShellStartMonitor(\r
VOID\r
)\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
if (EFI_ERROR(Status)) {\r
ShellPrintHiiEx(\r
- -1, \r
- -1, \r
+ -1,\r
+ -1,\r
NULL,\r
STRING_TOKEN (STR_SHELL_NO_IN_EX),\r
ShellInfoObject.HiiHandle);\r
&KeyData,\r
NotificationFunction,\r
&ShellInfoObject.CtrlCNotifyHandle1);\r
- \r
+\r
KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
if (!EFI_ERROR(Status)) {\r
Status = SimpleEx->RegisterKeyNotify(\r