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
- PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
- FreePool(AlignedNode);\r
+ AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
+ if (AlignedNode == NULL) {\r
+ FreePool (PathForReturn);\r
+ return NULL;\r
}\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 / 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
if (Cwd == NULL) {\r
return (NULL);\r
}\r
- Size = StrSize(Cwd) + StrSize(Path) - sizeof(CHAR16);\r
+ Size = StrSize(Cwd) + StrSize(Path);\r
NewPath = AllocateZeroPool(Size);\r
if (NewPath == NULL) {\r
return (NULL);\r
}\r
StrCpyS(NewPath, Size/sizeof(CHAR16), Cwd);\r
+ StrCatS(NewPath, Size/sizeof(CHAR16), L"\\");\r
if (*Path == L'\\') {\r
Path++;\r
while (PathRemoveLastItem(NewPath)) ;\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
return (EFI_UNSUPPORTED);\r
}\r
\r
- DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
+ if (NestingEnabled()) {\r
+ DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
\r
- DEBUG_CODE_BEGIN();\r
- Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
- FreePool(Temp);\r
- Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);\r
- FreePool(Temp);\r
- Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);\r
- FreePool(Temp);\r
- DEBUG_CODE_END();\r
+ DEBUG_CODE_BEGIN();\r
+ Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
+ FreePool(Temp);\r
+ Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);\r
+ FreePool(Temp);\r
+ Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);\r
+ FreePool(Temp);\r
+ DEBUG_CODE_END();\r
\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, CommandLine, 0);\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, CommandLine, 0);\r
\r
- Status = InternalShellExecuteDevicePath(\r
- ParentImageHandle,\r
- DevPath,\r
- Temp,\r
- (CONST CHAR16**)Environment,\r
- StatusCode);\r
+ Status = InternalShellExecuteDevicePath(\r
+ ParentImageHandle,\r
+ DevPath,\r
+ Temp,\r
+ (CONST CHAR16**)Environment,\r
+ StatusCode);\r
+\r
+ //\r
+ // de-allocate and return\r
+ //\r
+ FreePool(DevPath);\r
+ FreePool(Temp);\r
+ } else {\r
+ Status = InternalShellExecute(\r
+ (CONST CHAR16*)CommandLine,\r
+ (CONST CHAR16**)Environment,\r
+ StatusCode);\r
+ }\r
\r
- //\r
- // de-allocate and return\r
- //\r
- FreePool(DevPath);\r
- FreePool(Temp);\r
return(Status);\r
}\r
\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
CurDir = EfiShellGetCurDir(NULL);\r
ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));\r
StrnCatGrow(&Path2, &Path2Size, CurDir, 0);\r
+ StrnCatGrow(&Path2, &Path2Size, L"\\", 0);\r
if (*Path == L'\\') {\r
Path++;\r
while (PathRemoveLastItem(Path2)) ;\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. In both cases, the returned name includes the file system\r
mapping (i.e. fs0:\current-dir).\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
then the current working directory is returned.\r
\r
If the current working directory or the current working file system is changed then the\r
%cwd% environment variable will be updated\r
\r
+ Note that the current directory string should exclude the tailing backslash character.\r
+\r
@param FileSystem A pointer to the file system's mapped name. If NULL, then the current working\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
}\r
- if ((MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] != L'\\') || (MapListItem->CurrentDirectoryPath == NULL)) {\r
+ if ((MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') || (MapListItem->CurrentDirectoryPath == NULL)) {\r
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
- MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);\r
+ if (MapListItem->CurrentDirectoryPath != NULL) {\r
+ MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;\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
MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);\r
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0);\r
- if (MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] != L'\\') {\r
+ if (MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') {\r
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));\r
- MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);\r
+ MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;\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