X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ShellPkg%2FApplication%2FShell%2FShellProtocol.c;h=4e639fe35e4f289f3ea0401d981646cd15c63555;hb=6a5033ca3e8868a176a9671d55ad297bac385b1b;hp=fc13595dbb038727ce04564b4b9f5e4ac8023c2a;hpb=c617380446ec1228aa4c260b3eca775dbda5896b;p=mirror_edk2.git
diff --git a/ShellPkg/Application/Shell/ShellProtocol.c b/ShellPkg/Application/Shell/ShellProtocol.c
index fc13595dbb..4e639fe35e 100644
--- a/ShellPkg/Application/Shell/ShellProtocol.c
+++ b/ShellPkg/Application/Shell/ShellProtocol.c
@@ -3,14 +3,9 @@
manipulation, and initialization of EFI_SHELL_PROTOCOL.
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.
- Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -49,7 +44,6 @@ EfiShellClose (
@retval FALSE gEfiBlockIoProtocolGuid was not found.
**/
BOOLEAN
-EFIAPI
InternalShellProtocolIsBlockIoPresent(
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
@@ -79,7 +73,6 @@ InternalShellProtocolIsBlockIoPresent(
@retval FALSE gEfiSimpleFileSystemProtocolGuid was not found.
**/
BOOLEAN
-EFIAPI
InternalShellProtocolIsSimpleFileSystemPresent(
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
@@ -99,46 +92,11 @@ InternalShellProtocolIsSimpleFileSystemPresent(
return (FALSE);
}
-/**
- Internal worker debug helper function to print out maps as they are added.
-
- @param[in] Mapping string mapping that has been added
- @param[in] DevicePath pointer to device path that has been mapped.
-
- @retval EFI_SUCCESS the operation was successful.
- @return other an error ocurred
-
- @sa LocateHandle
- @sa OpenProtocol
-**/
-EFI_STATUS
-EFIAPI
-InternalShellProtocolDebugPrintMessage (
- IN CONST CHAR16 *Mapping,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- EFI_STATUS Status;
- CHAR16 *Temp;
-
- Status = EFI_SUCCESS;
- DEBUG_CODE_BEGIN();
-
- if (Mapping != NULL) {
- DEBUG((EFI_D_INFO, "Added new map item:\"%S\"\r\n", Mapping));
- }
- Temp = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
- DEBUG((EFI_D_INFO, "DevicePath: %S\r\n", Temp));
- FreePool(Temp);
-
- DEBUG_CODE_END();
- return (Status);
-}
/**
This function creates a mapping for a device path.
- If both DeviecPath and Mapping are NULL, this will reset the mapping to default values.
+ If both DevicePath and Mapping are NULL, this will reset the mapping to default values.
@param DevicePath Points to the device path. If this is NULL and Mapping points to a valid mapping,
then the mapping will be deleted.
@@ -185,13 +143,16 @@ EfiShellSetMap(
){
if (StringNoCaseCompare(&MapListNode->MapName, &Mapping) == 0) {
RemoveEntryList(&MapListNode->Link);
+ SHELL_FREE_NON_NULL(MapListNode->DevicePath);
+ SHELL_FREE_NON_NULL(MapListNode->MapName);
+ SHELL_FREE_NON_NULL(MapListNode->CurrentDirectoryPath);
FreePool(MapListNode);
return (EFI_SUCCESS);
}
} // for loop
//
- // We didnt find one to delete
+ // We didn't find one to delete
//
return (EFI_NOT_FOUND);
}
@@ -271,7 +232,7 @@ EfiShellGetDevicePathFromMap(
device path. If there is an exact match, the mapping is returned and *DevicePath
points to the end-of-device-path node.
- If there are multiple map names they will be semi-colon seperated in the
+ If there are multiple map names they will be semi-colon separated in the
NULL-terminated string.
@param DevicePath On entry, points to a device path pointer. On
@@ -449,38 +410,40 @@ EfiShellGetFilePathFromDevicePath(
; FilePath = (FILEPATH_DEVICE_PATH*)NextDevicePathNode (&FilePath->Header)
){
//
- // all the rest should be file path nodes
+ // If any node is not a file path node, then the conversion can not be completed
//
if ((DevicePathType(&FilePath->Header) != MEDIA_DEVICE_PATH) ||
(DevicePathSubType(&FilePath->Header) != MEDIA_FILEPATH_DP)) {
FreePool(PathForReturn);
- PathForReturn = NULL;
- ASSERT(FALSE);
- } else {
- //
- // append the path part onto the filepath.
- //
- ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));
-
- AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);
- ASSERT (AlignedNode != NULL);
-
- // File Path Device Path Nodes 'can optionally add a "\" separator to
- // the beginning and/or the end of the Path Name string.'
- // (UEFI Spec 2.4 section 9.3.6.4).
- // If necessary, add a "\", but otherwise don't
- // (This is specified in the above section, and also implied by the
- // UEFI Shell spec section 3.7)
- if ((PathSize != 0) &&
- (PathForReturn != NULL) &&
- (PathForReturn[PathSize - 1] != L'\\') &&
- (AlignedNode->PathName[0] != L'\\')) {
- PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);
- }
+ return NULL;
+ }
+
+ //
+ // append the path part onto the filepath.
+ //
+ ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));
+
+ AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);
+ if (AlignedNode == NULL) {
+ FreePool (PathForReturn);
+ return NULL;
+ }
- PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);
- FreePool(AlignedNode);
+ // File Path Device Path Nodes 'can optionally add a "\" separator to
+ // the beginning and/or the end of the Path Name string.'
+ // (UEFI Spec 2.4 section 9.3.6.4).
+ // If necessary, add a "\", but otherwise don't
+ // (This is specified in the above section, and also implied by the
+ // UEFI Shell spec section 3.7)
+ if ((PathSize != 0) &&
+ (PathForReturn != NULL) &&
+ (PathForReturn[PathSize / sizeof (CHAR16) - 1] != L'\\') &&
+ (AlignedNode->PathName[0] != L'\\')) {
+ PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);
}
+
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);
+ FreePool(AlignedNode);
} // for loop of remaining nodes
}
if (PathForReturn != NULL) {
@@ -595,7 +558,8 @@ EfiShellGetDevicePathFromFilePath(
//
// build the full device path
//
- if (*(Path+StrLen(MapName)+1) == CHAR_NULL) {
+ if ((*(Path+StrLen(MapName)) != CHAR_NULL) &&
+ (*(Path+StrLen(MapName)+1) == CHAR_NULL)) {
DevicePathForReturn = FileDevicePath(Handle, L"\\");
} else {
DevicePathForReturn = FileDevicePath(Handle, Path+StrLen(MapName));
@@ -823,7 +787,8 @@ EfiShellGetDeviceName(
@retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory
could not be opened.
@retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.
- @retval EFI_DEVICE_ERROR The device had an error
+ @retval EFI_DEVICE_ERROR The device had an error.
+ @retval Others Error status returned from EFI_SIMPLE_FILE_SYSTEM_PROTOCOL->OpenVolume().
**/
EFI_STATUS
EFIAPI
@@ -863,8 +828,12 @@ EfiShellOpenRootByHandle(
// Open the root volume now...
//
Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &RealFileHandle);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
*FileHandle = ConvertEfiFileProtocolToShellHandle(RealFileHandle, EfiShellGetMapFromDevicePath(&DevPath));
- return (Status);
+ return (EFI_SUCCESS);
}
/**
@@ -941,11 +910,10 @@ EfiShellBatchIsActive (
@param Attributes the File Attributes to use when creating a new file.
@retval EFI_SUCCESS the file is open and FileHandle is valid
- @retval EFI_UNSUPPORTED the device path cotained non-path elements
- @retval other an error ocurred.
+ @retval EFI_UNSUPPORTED the device path contained non-path elements
+ @retval other an error occurred.
**/
EFI_STATUS
-EFIAPI
InternalOpenFileDevicePath(
IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath,
OUT SHELL_FILE_HANDLE *FileHandle,
@@ -978,7 +946,7 @@ InternalOpenFileDevicePath(
Handle1 = ConvertShellHandleToEfiFileProtocol(ShellHandle);
if (Handle1 != NULL) {
//
- // chop off the begining part before the file system part...
+ // chop off the beginning part before the file system part...
//
///@todo BlockIo?
Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,
@@ -1096,14 +1064,14 @@ InternalOpenFileDevicePath(
already exists and is non-volatile then EFI_INVALID_PARAMETER is returned.
@param FileName Pointer to NULL-terminated file path
- @param FileAttribs The new file's attrbiutes. the different attributes are
+ @param FileAttribs The new file's attributes. the different attributes are
described in EFI_FILE_PROTOCOL.Open().
@param FileHandle On return, points to the created file handle or directory's handle
@retval EFI_SUCCESS The file was opened. FileHandle points to the new file's handle.
@retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
@retval EFI_UNSUPPORTED could not open the file path
- @retval EFI_NOT_FOUND the specified file could not be found on the devide, or could not
+ @retval EFI_NOT_FOUND the specified file could not be found on the device, or could not
file the file system on the device.
@retval EFI_NO_MEDIA the device has no medium.
@retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
@@ -1127,13 +1095,18 @@ EfiShellCreateFile(
{
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_STATUS Status;
+ BOOLEAN Volatile;
//
// Is this for an environment variable
// do we start with >v
//
if (StrStr(FileName, L">v") == FileName) {
- if (!IsVolatileEnv(FileName+2)) {
+ Status = IsVolatileEnv (FileName + 2, &Volatile);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (!Volatile) {
return (EFI_INVALID_PARAMETER);
}
*FileHandle = CreateFileInterfaceEnv(FileName+2);
@@ -1172,7 +1145,7 @@ EfiShellCreateFile(
@retval EFI_ACCESS_DENIED Guid already is assigned a name.
**/
EFI_STATUS
-EFIAPI
+EFIAPI
EfiShellRegisterGuidName(
IN CONST EFI_GUID *Guid,
IN CONST CHAR16 *GuidName
@@ -1243,6 +1216,7 @@ EfiShellOpenFileByName(
{
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_STATUS Status;
+ BOOLEAN Volatile;
*FileHandle = NULL;
@@ -1276,9 +1250,10 @@ EfiShellOpenFileByName(
}
//
- // Is this for NUL file
+ // Is this for NUL / NULL file
//
- if (StrCmp(FileName, L"NUL") == 0) {
+ if ((gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)FileName, L"NUL") == 0) ||
+ (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16*)FileName, L"NULL") == 0)) {
*FileHandle = &FileInterfaceNulFile;
return (EFI_SUCCESS);
}
@@ -1302,7 +1277,11 @@ EfiShellOpenFileByName(
// do we start with >v
//
if (StrStr(FileName, L">v") == FileName) {
- if (!IsVolatileEnv(FileName+2) &&
+ Status = IsVolatileEnv (FileName + 2, &Volatile);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (!Volatile &&
((OpenMode & EFI_FILE_MODE_WRITE) != 0)) {
return (EFI_INVALID_PARAMETER);
}
@@ -1314,7 +1293,7 @@ EfiShellOpenFileByName(
// We are opening a regular file.
//
DevicePath = EfiShellGetDevicePathFromFilePath(FileName);
-// DEBUG_CODE(InternalShellProtocolDebugPrintMessage (NULL, DevicePath););
+
if (DevicePath == NULL) {
return (EFI_NOT_FOUND);
}
@@ -1362,6 +1341,7 @@ EfiShellDeleteFileByName(
//
// now delete the file
//
+ ShellFileHandleRemove(FileHandle);
return (ShellInfoObject.NewEfiShellProtocol->DeleteFile(FileHandle));
}
@@ -1402,7 +1382,7 @@ EfiShellEnablePageBreak (
variables with the format 'x=y', where x is the
environment variable name and y is the value. If this
is NULL, then the current shell environment is used.
-
+
@param[out] StartImageStatus Returned status from gBS->StartImage.
@retval EFI_SUCCESS The command executed successfully. The status code
@@ -1412,7 +1392,6 @@ EfiShellEnablePageBreak (
@retval EFI_UNSUPPORTED Nested shell invocations are not allowed.
**/
EFI_STATUS
-EFIAPI
InternalShellExecuteDevicePath(
IN CONST EFI_HANDLE *ParentImageHandle,
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
@@ -1438,9 +1417,10 @@ InternalShellExecuteDevicePath(
}
InitializeListHead(&OrigEnvs);
+ ZeroMem(&ShellParamsProtocol, sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));
NewHandle = NULL;
-
+
NewCmdLine = AllocateCopyPool (StrSize (CommandLine), CommandLine);
if (NewCmdLine == NULL) {
return EFI_OUT_OF_RESOURCES;
@@ -1468,6 +1448,7 @@ InternalShellExecuteDevicePath(
if (NewHandle != NULL) {
gBS->UnloadImage(NewHandle);
}
+ FreePool (NewCmdLine);
return (Status);
}
Status = gBS->OpenProtocol(
@@ -1479,6 +1460,20 @@ InternalShellExecuteDevicePath(
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (!EFI_ERROR(Status)) {
+ //
+ // If the image is not an app abort it.
+ //
+ if (LoadedImage->ImageCodeType != EfiLoaderCode){
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SHELL_IMAGE_NOT_APP),
+ ShellInfoObject.HiiHandle
+ );
+ goto UnloadImage;
+ }
+
ASSERT(LoadedImage->LoadOptionsSize == 0);
if (NewCmdLine != NULL) {
LoadedImage->LoadOptionsSize = (UINT32)StrSize(NewCmdLine);
@@ -1501,8 +1496,11 @@ InternalShellExecuteDevicePath(
ShellParamsProtocol.StdIn = ShellInfoObject.NewShellParametersProtocol->StdIn;
ShellParamsProtocol.StdOut = ShellInfoObject.NewShellParametersProtocol->StdOut;
ShellParamsProtocol.StdErr = ShellInfoObject.NewShellParametersProtocol->StdErr;
- Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, NULL, NULL);
- ASSERT_EFI_ERROR(Status);
+ Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, Efi_Application, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ goto UnloadImage;
+ }
+
//
// Replace Argv[0] with the full path of the binary we're executing:
// If the command line was "foo", the binary might be called "foo.efi".
@@ -1584,6 +1582,108 @@ FreeAlloc:
return(Status);
}
+
+/**
+ internal worker function to load and run an image in the current shell.
+
+ @param CommandLine Points to the NULL-terminated UCS-2 encoded string
+ containing the command line. If NULL then the command-
+ line will be empty.
+ @param Environment Points to a NULL-terminated array of environment
+ variables with the format 'x=y', where x is the
+ environment variable name and y is the value. If this
+ is NULL, then the current shell environment is used.
+
+ @param[out] StartImageStatus Returned status from the command line.
+
+ @retval EFI_SUCCESS The command executed successfully. The status code
+ returned by the command is pointed to by StatusCode.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED Nested shell invocations are not allowed.
+**/
+EFI_STATUS
+InternalShellExecute(
+ IN CONST CHAR16 *CommandLine OPTIONAL,
+ IN CONST CHAR16 **Environment OPTIONAL,
+ OUT EFI_STATUS *StartImageStatus OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS CleanupStatus;
+ LIST_ENTRY OrigEnvs;
+
+ InitializeListHead(&OrigEnvs);
+
+ //
+ // Save our current environment settings for later restoration if necessary
+ //
+ if (Environment != NULL) {
+ Status = GetEnvironmentVariableList(&OrigEnvs);
+ if (!EFI_ERROR(Status)) {
+ Status = SetEnvironmentVariables(Environment);
+ } else {
+ return Status;
+ }
+ }
+
+ Status = RunShellCommand(CommandLine, StartImageStatus);
+
+ // Restore environment variables
+ if (!IsListEmpty(&OrigEnvs)) {
+ CleanupStatus = SetEnvironmentVariableList(&OrigEnvs);
+ ASSERT_EFI_ERROR (CleanupStatus);
+ }
+
+ return(Status);
+}
+
+/**
+ Determine if the UEFI Shell is currently running with nesting enabled or disabled.
+
+ @retval FALSE nesting is required
+ @retval other nesting is enabled
+**/
+STATIC
+BOOLEAN
+NestingEnabled(
+ VOID
+)
+{
+ EFI_STATUS Status;
+ CHAR16 *Temp;
+ CHAR16 *Temp2;
+ UINTN TempSize;
+ BOOLEAN RetVal;
+
+ RetVal = TRUE;
+ Temp = NULL;
+ Temp2 = NULL;
+
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {
+ TempSize = 0;
+ Temp = NULL;
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Temp = AllocateZeroPool(TempSize + sizeof(CHAR16));
+ if (Temp != NULL) {
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);
+ }
+ }
+ Temp2 = StrnCatGrow(&Temp2, NULL, mNoNestingTrue, 0);
+ if (Temp != NULL && Temp2 != NULL && StringNoCaseCompare(&Temp, &Temp2) == 0) {
+ //
+ // Use the no nesting method.
+ //
+ RetVal = FALSE;
+ }
+ }
+
+ SHELL_FREE_NON_NULL(Temp);
+ SHELL_FREE_NON_NULL(Temp2);
+ return (RetVal);
+}
+
/**
Execute the command line.
@@ -1607,7 +1707,7 @@ FreeAlloc:
variables with the format 'x=y', where x is the
environment variable name and y is the value. If this
is NULL, then the current shell environment is used.
- @param StatusCode Points to the status code returned by the command.
+ @param StatusCode Points to the status code returned by the CommandLine.
@retval EFI_SUCCESS The command executed successfully. The status code
returned by the command is pointed to by StatusCode.
@@ -1631,19 +1731,14 @@ EfiShellExecute(
CHAR16 *Temp;
EFI_DEVICE_PATH_PROTOCOL *DevPath;
UINTN Size;
- EFI_STATUS CalleeStatusCode;
- CalleeStatusCode = EFI_SUCCESS;
-
if ((PcdGet8(PcdShellSupportLevel) < 1)) {
return (EFI_UNSUPPORTED);
}
- if (Environment != NULL) {
- // If Environment isn't null, load a new image of the shell with its own
- // environment
+ if (NestingEnabled()) {
DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);
-
+
DEBUG_CODE_BEGIN();
Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);
FreePool(Temp);
@@ -1656,7 +1751,7 @@ EfiShellExecute(
Temp = NULL;
Size = 0;
ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));
- StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);
+ StrnCatGrow(&Temp, &Size, L"Shell.efi -exit ", 0);
StrnCatGrow(&Temp, &Size, CommandLine, 0);
Status = InternalShellExecuteDevicePath(
@@ -1672,19 +1767,10 @@ EfiShellExecute(
FreePool(DevPath);
FreePool(Temp);
} else {
- // If Environment is NULL, we are free to use and mutate the current shell
- // environment. This is much faster as uses much less memory.
-
- if (CommandLine == NULL) {
- CommandLine = L"";
- }
-
- Status = RunShellCommand (CommandLine, &CalleeStatusCode);
-
- // Pass up the command's exit code if the caller wants it
- if (StatusCode != NULL) {
- *StatusCode = (EFI_STATUS) CalleeStatusCode;
- }
+ Status = InternalShellExecute(
+ (CONST CHAR16*)CommandLine,
+ (CONST CHAR16**)Environment,
+ StatusCode);
}
return(Status);
@@ -1699,7 +1785,6 @@ EfiShellExecute(
@param FileListNode pointer to the list node to free
**/
VOID
-EFIAPI
InternalFreeShellFileInfoNode(
IN EFI_SHELL_FILE_INFO *FileListNode
)
@@ -1823,11 +1908,10 @@ typedef struct {
@param[in] Node The node to copy from.
@param[in] Save TRUE to set Node->Handle to NULL, FALSE otherwise.
- @retval NULL a memory allocation error ocurred
+ @retval NULL a memory allocation error occurred
@return != NULL a pointer to the new node
**/
EFI_SHELL_FILE_INFO*
-EFIAPI
InternalDuplicateShellFileInfo(
IN EFI_SHELL_FILE_INFO *Node,
IN BOOLEAN Save
@@ -1876,11 +1960,10 @@ InternalDuplicateShellFileInfo(
@param[in] Handle Handle member initial value.
@param[in] Info Info struct to copy.
- @retval NULL An error ocurred.
+ @retval NULL An error occurred.
@return a pointer to the newly allocated structure.
**/
EFI_SHELL_FILE_INFO *
-EFIAPI
CreateAndPopulateShellFileInfo(
IN CONST CHAR16 *BasePath,
IN CONST EFI_STATUS Status,
@@ -2024,20 +2107,29 @@ EfiShellFindFilesInDir(
; !EFI_ERROR(Status) && !NoFile
; Status = FileHandleFindNextFile(FileDirHandle, FileInfo, &NoFile)
){
+ if (ShellFileList == NULL) {
+ ShellFileList = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
+ if (ShellFileList == NULL) {
+ SHELL_FREE_NON_NULL (BasePath);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ InitializeListHead(&ShellFileList->Link);
+ }
//
// allocate a new EFI_SHELL_FILE_INFO and populate it...
//
ShellFileListItem = CreateAndPopulateShellFileInfo(
BasePath,
- EFI_SUCCESS, // success since we didnt fail to open it...
+ EFI_SUCCESS, // success since we didn't fail to open it...
FileInfo->FileName,
NULL, // no handle since not open
FileInfo);
-
- if (ShellFileList == NULL) {
- ShellFileList = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
- ASSERT(ShellFileList != NULL);
- InitializeListHead(&ShellFileList->Link);
+ if (ShellFileListItem == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ //
+ // Free resources outside the loop.
+ //
+ break;
}
InsertTailList(&ShellFileList->Link, &ShellFileListItem->Link);
}
@@ -2069,7 +2161,7 @@ EfiShellFindFilesInDir(
@retval EFI_NOT_FOUND GuidName is not a known GUID Name.
**/
EFI_STATUS
-EFIAPI
+EFIAPI
EfiShellGetGuidFromName(
IN CONST CHAR16 *GuidName,
OUT EFI_GUID *Guid
@@ -2081,11 +2173,11 @@ EfiShellGetGuidFromName(
if (Guid == NULL || GuidName == NULL) {
return (EFI_INVALID_PARAMETER);
}
-
+
Status = GetGuidFromStringName(GuidName, NULL, &NewGuid);
if (!EFI_ERROR(Status)) {
- CopyGuid(NewGuid, Guid);
+ CopyGuid(Guid, NewGuid);
}
return (Status);
@@ -2109,7 +2201,7 @@ EfiShellGetGuidFromName(
@retval EFI_NOT_FOUND Guid is not assigned a name.
**/
EFI_STATUS
-EFIAPI
+EFIAPI
EfiShellGetGuidName(
IN CONST EFI_GUID *Guid,
OUT CONST CHAR16 **GuidName
@@ -2132,53 +2224,7 @@ EfiShellGetGuidName(
return (EFI_SUCCESS);
}
-/**
- Updates a file name to be preceeded by the mapped drive name
-
- @param[in] BasePath the Mapped drive name to prepend
- @param[in, out] Path pointer to pointer to the file name to update.
-
- @retval EFI_SUCCESS
- @retval EFI_OUT_OF_RESOURCES
-**/
-EFI_STATUS
-EFIAPI
-UpdateFileName(
- IN CONST CHAR16 *BasePath,
- IN OUT CHAR16 **Path
- )
-{
- CHAR16 *Path2;
- UINTN Path2Size;
-
- Path2Size = 0;
- Path2 = NULL;
-
- ASSERT(Path != NULL);
- ASSERT(*Path != NULL);
- ASSERT(BasePath != NULL);
-
- //
- // convert a local path to an absolute path
- //
- if (StrStr(*Path, L":") == NULL) {
- ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));
- StrnCatGrow(&Path2, &Path2Size, BasePath, 0);
- if (Path2 == NULL) {
- return (EFI_OUT_OF_RESOURCES);
- }
- ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));
- StrnCatGrow(&Path2, &Path2Size, (*Path)[0] == L'\\'?(*Path) + 1 :*Path, 0);
- if (Path2 == NULL) {
- return (EFI_OUT_OF_RESOURCES);
- }
- }
-
- FreePool(*Path);
- (*Path) = Path2;
- return (EFI_SUCCESS);
-}
/**
If FileHandle is a directory then the function reads from FileHandle and reads in
@@ -2203,7 +2249,6 @@ UpdateFileName(
@retval EFI_OUT_OF_RESOURCES a memory allocation failed
**/
EFI_STATUS
-EFIAPI
ShellSearchHandle(
IN CONST CHAR16 *FilePattern,
IN EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation,
@@ -2242,7 +2287,10 @@ ShellSearchHandle(
; NextFilePatternStart++);
CurrentFilePattern = AllocateZeroPool((NextFilePatternStart-FilePattern+1)*sizeof(CHAR16));
- ASSERT(CurrentFilePattern != NULL);
+ if (CurrentFilePattern == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
StrnCpyS(CurrentFilePattern, NextFilePatternStart-FilePattern+1, FilePattern, NextFilePatternStart-FilePattern);
if (CurrentFilePattern[0] == CHAR_NULL
@@ -2301,15 +2349,14 @@ ShellSearchHandle(
){
if (UnicodeCollation->MetaiMatch(UnicodeCollation, (CHAR16*)ShellInfoNode->FileName, CurrentFilePattern)){
if (ShellInfoNode->FullName != NULL && StrStr(ShellInfoNode->FullName, L":") == NULL) {
- Size = StrSize(ShellInfoNode->FullName);
- Size += StrSize(MapName) + sizeof(CHAR16);
+ Size = StrSize (ShellInfoNode->FullName) + StrSize (MapName);
NewFullName = AllocateZeroPool(Size);
if (NewFullName == NULL) {
Status = EFI_OUT_OF_RESOURCES;
} else {
- StrCpyS(NewFullName, Size/sizeof(CHAR16), MapName);
- StrCatS(NewFullName, Size/sizeof(CHAR16), ShellInfoNode->FullName+1);
- FreePool((VOID*)ShellInfoNode->FullName);
+ StrCpyS(NewFullName, Size / sizeof(CHAR16), MapName);
+ StrCatS(NewFullName, Size / sizeof(CHAR16), ShellInfoNode->FullName);
+ FreePool ((VOID *) ShellInfoNode->FullName);
ShellInfoNode->FullName = NewFullName;
}
}
@@ -2339,6 +2386,8 @@ ShellSearchHandle(
// recurse with the next part of the pattern
//
Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode, MapName);
+ EfiShellClose(ShellInfoNode->Handle);
+ ShellInfoNode->Handle = NULL;
}
} else if (!EFI_ERROR(Status)) {
//
@@ -2349,7 +2398,6 @@ ShellSearchHandle(
// copy the information we need into a new Node
//
NewShellNode = InternalDuplicateShellFileInfo(ShellInfoNode, FALSE);
- ASSERT(NewShellNode != NULL);
if (NewShellNode == NULL) {
Status = EFI_OUT_OF_RESOURCES;
}
@@ -2376,6 +2424,10 @@ ShellSearchHandle(
}
}
+ if (*FileList == NULL || (*FileList != NULL && IsListEmpty(&(*FileList)->Link))) {
+ Status = EFI_NOT_FOUND;
+ }
+
FreePool(CurrentFilePattern);
return (Status);
}
@@ -2438,8 +2490,8 @@ EfiShellFindFiles(
PatternCopy = PathCleanUpDirectories(PatternCopy);
- Count = StrStr(PatternCopy, L":") - PatternCopy;
- Count += 2;
+ Count = StrStr(PatternCopy, L":") - PatternCopy + 1;
+ ASSERT (Count <= StrLen (PatternCopy));
ASSERT(MapName == NULL);
MapName = StrnCatGrow(&MapName, NULL, PatternCopy, Count);
@@ -2457,6 +2509,7 @@ EfiShellFindFiles(
; PatternCurrentLocation++);
PatternCurrentLocation++;
Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL, MapName);
+ EfiShellClose(RootFileHandle);
}
FreePool(RootDevicePath);
}
@@ -2586,7 +2639,7 @@ EfiShellOpenFileList(
pointer does not need to be freed by the caller.
**/
CONST CHAR16 *
-EFIAPI
+EFIAPI
EfiShellGetEnvEx(
IN CONST CHAR16 *Name,
OUT UINT32 *Attributes OPTIONAL
@@ -2595,7 +2648,6 @@ EfiShellGetEnvEx(
EFI_STATUS Status;
VOID *Buffer;
UINTN Size;
- LIST_ENTRY List;
ENV_VAR_LIST *Node;
CHAR16 *CurrentWriteLocation;
@@ -2603,21 +2655,13 @@ EfiShellGetEnvEx(
Buffer = NULL;
if (Name == NULL) {
- //
- // Get all our environment variables
- //
- InitializeListHead(&List);
- Status = GetEnvironmentVariableList(&List);
- if (EFI_ERROR(Status)){
- return (NULL);
- }
//
// Build the semi-colon delimited list. (2 passes)
//
- for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List)
- ; !IsNull(&List, &Node->Link)
- ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link)
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)
+ ; !IsNull(&gShellEnvVarList.Link, &Node->Link)
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)
){
ASSERT(Node->Key != NULL);
Size += StrSize(Node->Key);
@@ -2627,56 +2671,59 @@ EfiShellGetEnvEx(
Buffer = AllocateZeroPool(Size);
if (Buffer == NULL) {
- if (!IsListEmpty (&List)) {
- FreeEnvironmentVariableList(&List);
- }
return (NULL);
}
CurrentWriteLocation = (CHAR16*)Buffer;
- for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List)
- ; !IsNull(&List, &Node->Link)
- ; Node = (ENV_VAR_LIST*)GetNextNode(&List, &Node->Link)
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)
+ ; !IsNull(&gShellEnvVarList.Link, &Node->Link)
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)
){
ASSERT(Node->Key != NULL);
- StrCpyS( CurrentWriteLocation,
- (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)),
+ StrCpyS( CurrentWriteLocation,
+ (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)),
Node->Key
);
CurrentWriteLocation += StrLen(CurrentWriteLocation) + 1;
}
- //
- // Free the list...
- //
- if (!IsListEmpty (&List)) {
- FreeEnvironmentVariableList(&List);
- }
} else {
//
// We are doing a specific environment variable
//
+ Status = ShellFindEnvVarInList(Name, (CHAR16**)&Buffer, &Size, Attributes);
- //
- // get the size we need for this EnvVariable
- //
- Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);
- if (Status == EFI_BUFFER_TOO_SMALL) {
+ if (EFI_ERROR(Status)){
//
- // Allocate the space and recall the get function
+ // get the size we need for this EnvVariable
//
- Buffer = AllocateZeroPool(Size);
Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);
- }
- //
- // we didnt get it (might not exist)
- // free the memory if we allocated any and return NULL
- //
- if (EFI_ERROR(Status)) {
- if (Buffer != NULL) {
- FreePool(Buffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Allocate the space and recall the get function
+ //
+ Buffer = AllocateZeroPool(Size);
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);
+ }
+ //
+ // we didn't get it (might not exist)
+ // free the memory if we allocated any and return NULL
+ //
+ if (EFI_ERROR(Status)) {
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+ return (NULL);
+ } else {
+ //
+ // If we did not find the environment variable in the gShellEnvVarList
+ // but get it from UEFI variable storage successfully then we need update
+ // the gShellEnvVarList.
+ //
+ ShellFreeEnvVarList ();
+ Status = ShellInitEnvVarList ();
+ ASSERT (Status == EFI_SUCCESS);
}
- return (NULL);
}
}
@@ -2729,23 +2776,35 @@ EfiShellGetEnv(
@retval EFI_SUCCESS The environment variable was successfully updated.
**/
EFI_STATUS
-EFIAPI
InternalEfiShellSetEnv(
IN CONST CHAR16 *Name,
IN CONST CHAR16 *Value,
IN BOOLEAN Volatile
)
{
+ EFI_STATUS Status;
+
if (Value == NULL || StrLen(Value) == 0) {
- return (SHELL_DELETE_ENVIRONMENT_VARIABLE(Name));
+ Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Name);
+ if (!EFI_ERROR(Status)) {
+ ShellRemvoeEnvVarFromList(Name);
+ }
} else {
SHELL_DELETE_ENVIRONMENT_VARIABLE(Name);
- if (Volatile) {
- return (SHELL_SET_ENVIRONMENT_VARIABLE_V(Name, StrSize(Value), Value));
- } else {
- return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(Name, StrSize(Value), Value));
+ Status = ShellAddEnvVarToList(
+ Name, Value, StrSize(Value),
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | (Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE)
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = Volatile
+ ? SHELL_SET_ENVIRONMENT_VARIABLE_V (Name, StrSize (Value) - sizeof (CHAR16), Value)
+ : SHELL_SET_ENVIRONMENT_VARIABLE_NV (Name, StrSize (Value) - sizeof (CHAR16), Value);
+ if (EFI_ERROR (Status)) {
+ ShellRemvoeEnvVarFromList(Name);
+ }
}
}
+ return Status;
}
/**
@@ -2783,31 +2842,15 @@ EfiShellSetEnv(
//
// Make sure we dont 'set' a predefined read only variable
//
- if (gUnicodeCollation->StriColl(
- gUnicodeCollation,
- (CHAR16*)Name,
- L"cwd") == 0
- ||gUnicodeCollation->StriColl(
- gUnicodeCollation,
- (CHAR16*)Name,
- L"Lasterror") == 0
- ||gUnicodeCollation->StriColl(
- gUnicodeCollation,
- (CHAR16*)Name,
- L"profiles") == 0
- ||gUnicodeCollation->StriColl(
- gUnicodeCollation,
- (CHAR16*)Name,
- L"uefishellsupport") == 0
- ||gUnicodeCollation->StriColl(
- gUnicodeCollation,
- (CHAR16*)Name,
- L"uefishellversion") == 0
- ||gUnicodeCollation->StriColl(
- gUnicodeCollation,
- (CHAR16*)Name,
- L"uefiversion") == 0
- ){
+ if ((StrCmp (Name, L"cwd") == 0) ||
+ (StrCmp (Name, L"lasterror") == 0) ||
+ (StrCmp (Name, L"profiles") == 0) ||
+ (StrCmp (Name, L"uefishellsupport") == 0) ||
+ (StrCmp (Name, L"uefishellversion") == 0) ||
+ (StrCmp (Name, L"uefiversion") == 0) ||
+ (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest &&
+ StrCmp (Name, mNoNestingEnvVarName) == 0)
+ ) {
return (EFI_INVALID_PARAMETER);
}
return (InternalEfiShellSetEnv(Name, Value, Volatile));
@@ -2820,7 +2863,7 @@ EfiShellSetEnv(
FileSystemMapping is not NULL, it returns the current directory associated with the
FileSystemMapping. In both cases, the returned name includes the file system
mapping (i.e. fs0:\current-dir).
-
+
Note that the current directory string should exclude the tailing backslash character.
@param FileSystemMapping A pointer to the file system mapping. If NULL,
@@ -2884,7 +2927,7 @@ EfiShellGetCurDir(
directory is changed.
@param Dir Points to the NULL-terminated directory on the device specified by FileSystem.
- @retval EFI_SUCCESS The operation was sucessful
+ @retval EFI_SUCCESS The operation was successful
@retval EFI_NOT_FOUND The file system could not be found
**/
EFI_STATUS
@@ -2940,13 +2983,15 @@ EfiShellSetCurDir(
// make that the current file system mapping
//
if (MapListItem != NULL) {
- gShellCurDir = MapListItem;
+ gShellCurMapping = MapListItem;
}
} else {
- MapListItem = gShellCurDir;
+ MapListItem = gShellCurMapping;
}
if (MapListItem == NULL) {
+ FreePool (DirectoryName);
+ SHELL_FREE_NON_NULL(MapName);
return (EFI_NOT_FOUND);
}
@@ -2963,6 +3008,7 @@ EfiShellSetCurDir(
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName+StrLen(MapName), 0);
}
+ FreePool (MapName);
} else {
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0);
@@ -2971,13 +3017,14 @@ EfiShellSetCurDir(
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
if (MapListItem->CurrentDirectoryPath != NULL) {
MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;
- }
+ }
}
} else {
//
// cant have a mapping in the directory...
//
if (StrStr(DirectoryName, L":") != NULL) {
+ FreePool (DirectoryName);
return (EFI_INVALID_PARAMETER);
}
//
@@ -2985,9 +3032,10 @@ EfiShellSetCurDir(
//
MapListItem = ShellCommandFindMapItem(FileSystem);
if (MapListItem == NULL) {
+ FreePool (DirectoryName);
return (EFI_INVALID_PARAMETER);
}
-// gShellCurDir = MapListItem;
+// gShellCurMapping = MapListItem;
if (DirectoryName != NULL) {
//
// change current dir on that file system
@@ -3009,10 +3057,11 @@ EfiShellSetCurDir(
}
}
}
+ FreePool (DirectoryName);
//
// if updated the current directory then update the environment variable
//
- if (MapListItem == gShellCurDir) {
+ if (MapListItem == gShellCurMapping) {
Size = 0;
ASSERT((TempString == NULL && Size == 0) || (TempString != NULL));
StrnCatGrow(&TempString, &Size, MapListItem->MapName, 0);
@@ -3077,11 +3126,13 @@ EfiShellGetHelpText(
&& (Command[StrLen(Command)-4] == L'.')
) {
FixCommand = AllocateZeroPool(StrSize(Command) - 4 * sizeof (CHAR16));
- ASSERT(FixCommand != NULL);
+ if (FixCommand == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
- StrnCpyS( FixCommand,
- (StrSize(Command) - 4 * sizeof (CHAR16))/sizeof(CHAR16),
- Command,
+ StrnCpyS( FixCommand,
+ (StrSize(Command) - 4 * sizeof (CHAR16))/sizeof(CHAR16),
+ Command,
StrLen(Command)-4
);
Status = ProcessManFile(FixCommand, FixCommand, Sections, NULL, HelpText);
@@ -3128,20 +3179,20 @@ EfiShellIsRootShell(
}
/**
- function to return a semi-colon delimeted list of all alias' in the current shell
+ function to return a semi-colon delimited list of all alias' in the current shell
up to caller to free the memory.
@retval NULL No alias' were found
- @retval NULL An error ocurred getting alias'
+ @retval NULL An error occurred getting alias'
@return !NULL a list of all alias'
**/
CHAR16 *
-EFIAPI
InternalEfiShellGetListAlias(
+ VOID
)
{
-
+
EFI_STATUS Status;
EFI_GUID Guid;
CHAR16 *VariableName;
@@ -3176,17 +3227,17 @@ InternalEfiShellGetListAlias(
RetVal = NULL;
break;
}
-
+
NameSize = NameBufferSize;
Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
}
-
+
if (EFI_ERROR (Status)) {
SHELL_FREE_NON_NULL(RetVal);
RetVal = NULL;
break;
}
-
+
if (CompareGuid(&Guid, &gShellAliasGuid)){
ASSERT((RetVal == NULL && RetSize == 0) || (RetVal != NULL));
RetVal = StrnCatGrow(&RetVal, &RetSize, VariableName, 0);
@@ -3201,10 +3252,10 @@ InternalEfiShellGetListAlias(
/**
Convert a null-terminated unicode string, in-place, to all lowercase.
Then return it.
-
+
@param Str The null-terminated string to be converted to all lowercase.
-
- @return The null-terminated string converted into all lowercase.
+
+ @return The null-terminated string converted into all lowercase.
**/
CHAR16 *
ToLower (
@@ -3231,12 +3282,12 @@ ToLower (
@param[out] Volatile upon return of a single command if TRUE indicates
this is stored in a volatile fashion. FALSE otherwise.
- @return If Alias is not NULL, it will return a pointer to
+ @return If Alias is not NULL, it will return a pointer to
the NULL-terminated command for that alias.
If Alias is NULL, ReturnedData points to a ';'
delimited list of alias (e.g.
ReturnedData = "dir;del;copy;mfp") that is NULL-terminated.
- @retval NULL an error ocurred
+ @retval NULL an error occurred
@retval NULL Alias was not a valid Alias
**/
CONST CHAR16 *
@@ -3256,11 +3307,14 @@ EfiShellGetAlias(
// Convert to lowercase to make aliases case-insensitive
if (Alias != NULL) {
AliasLower = AllocateCopyPool (StrSize (Alias), Alias);
- ASSERT (AliasLower != NULL);
+ if (AliasLower == NULL) {
+ return NULL;
+ }
ToLower (AliasLower);
if (Volatile == NULL) {
GetVariable2 (AliasLower, &gShellAliasGuid, (VOID **)&AliasVal, NULL);
+ FreePool(AliasLower);
return (AddBufferToFreeList(AliasVal));
}
RetSize = 0;
@@ -3274,6 +3328,7 @@ EfiShellGetAlias(
if (RetVal != NULL) {
FreePool(RetVal);
}
+ FreePool(AliasLower);
return (NULL);
}
if ((EFI_VARIABLE_NON_VOLATILE & Attribs) == EFI_VARIABLE_NON_VOLATILE) {
@@ -3305,7 +3360,6 @@ EfiShellGetAlias(
@retval EFI_NOT_FOUND the Alias intended to be deleted was not found
**/
EFI_STATUS
-EFIAPI
InternalSetAlias(
IN CONST CHAR16 *Command,
IN CONST CHAR16 *Alias,
@@ -3314,38 +3368,40 @@ InternalSetAlias(
{
EFI_STATUS Status;
CHAR16 *AliasLower;
+ BOOLEAN DeleteAlias;
- // Convert to lowercase to make aliases case-insensitive
- if (Alias != NULL) {
- AliasLower = AllocateCopyPool (StrSize (Alias), Alias);
- ASSERT (AliasLower != NULL);
- ToLower (AliasLower);
- } else {
- AliasLower = NULL;
- }
-
- //
- // We must be trying to remove one if Alias is NULL
- //
+ DeleteAlias = FALSE;
if (Alias == NULL) {
//
+ // We must be trying to remove one if Alias is NULL
// remove an alias (but passed in COMMAND parameter)
//
- Status = (gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL));
- } else {
- //
- // Add and replace are the same
- //
-
- // We dont check the error return on purpose since the variable may not exist.
- gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL);
+ Alias = Command;
+ DeleteAlias = TRUE;
+ }
+ ASSERT (Alias != NULL);
- Status = (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command));
+ //
+ // Convert to lowercase to make aliases case-insensitive
+ //
+ AliasLower = AllocateCopyPool (StrSize (Alias), Alias);
+ if (AliasLower == NULL) {
+ return EFI_OUT_OF_RESOURCES;
}
+ ToLower (AliasLower);
- if (Alias != NULL) {
- FreePool (AliasLower);
+ if (DeleteAlias) {
+ Status = gRT->SetVariable (AliasLower, &gShellAliasGuid, 0, 0, NULL);
+ } else {
+ Status = gRT->SetVariable (
+ AliasLower, &gShellAliasGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | (Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE),
+ StrSize (Command), (VOID *) Command
+ );
}
+
+ FreePool (AliasLower);
+
return Status;
}
@@ -3467,7 +3523,6 @@ EFI_SHELL_PROTOCOL mShellProtocol = {
@return An error from LocateHandle, CreateEvent, or other core function.
**/
EFI_STATUS
-EFIAPI
CreatePopulateInstallShellProtocol (
IN OUT EFI_SHELL_PROTOCOL **NewShell
)
@@ -3477,6 +3532,7 @@ CreatePopulateInstallShellProtocol (
EFI_HANDLE *Buffer;
UINTN HandleCounter;
SHELL_PROTOCOL_HANDLE_LIST *OldProtocolNode;
+ EFI_SHELL_PROTOCOL *OldShell;
if (NewShell == NULL) {
return (EFI_INVALID_PARAMETER);
@@ -3528,20 +3584,27 @@ CreatePopulateInstallShellProtocol (
// now overwrite each of them, but save the info to restore when we end.
//
for (HandleCounter = 0 ; HandleCounter < (BufferSize/sizeof(EFI_HANDLE)) ; HandleCounter++) {
- OldProtocolNode = AllocateZeroPool(sizeof(SHELL_PROTOCOL_HANDLE_LIST));
- ASSERT(OldProtocolNode != NULL);
Status = gBS->OpenProtocol(Buffer[HandleCounter],
&gEfiShellProtocolGuid,
- (VOID **) &(OldProtocolNode->Interface),
+ (VOID **) &OldShell,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (!EFI_ERROR(Status)) {
+ OldProtocolNode = AllocateZeroPool(sizeof(SHELL_PROTOCOL_HANDLE_LIST));
+ if (OldProtocolNode == NULL) {
+ if (!IsListEmpty (&ShellInfoObject.OldShellList.Link)) {
+ CleanUpShellProtocol (&mShellProtocol);
+ }
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
//
// reinstall over the old one...
//
- OldProtocolNode->Handle = Buffer[HandleCounter];
+ OldProtocolNode->Handle = Buffer[HandleCounter];
+ OldProtocolNode->Interface = OldShell;
Status = gBS->ReinstallProtocolInterface(
OldProtocolNode->Handle,
&gEfiShellProtocolGuid,
@@ -3549,7 +3612,7 @@ CreatePopulateInstallShellProtocol (
(VOID*)(&mShellProtocol));
if (!EFI_ERROR(Status)) {
//
- // we reinstalled sucessfully. log this so we can reverse it later.
+ // we reinstalled successfully. log this so we can reverse it later.
//
//
@@ -3594,38 +3657,50 @@ CreatePopulateInstallShellProtocol (
@retval EFI_SUCCESS The operation was successful.
**/
EFI_STATUS
-EFIAPI
CleanUpShellProtocol (
IN OUT EFI_SHELL_PROTOCOL *NewShell
)
{
- EFI_STATUS Status;
SHELL_PROTOCOL_HANDLE_LIST *Node2;
- EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
//
// if we need to restore old protocols...
//
if (!IsListEmpty(&ShellInfoObject.OldShellList.Link)) {
- for (Node2 = (SHELL_PROTOCOL_HANDLE_LIST *)GetFirstNode(&ShellInfoObject.OldShellList.Link)
+ for (Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link)
; !IsListEmpty (&ShellInfoObject.OldShellList.Link)
- ; Node2 = (SHELL_PROTOCOL_HANDLE_LIST *)GetFirstNode(&ShellInfoObject.OldShellList.Link)
- ){
- RemoveEntryList(&Node2->Link);
- Status = gBS->ReinstallProtocolInterface(Node2->Handle,
- &gEfiShellProtocolGuid,
- NewShell,
- Node2->Interface);
- FreePool(Node2);
+ ; Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link)
+ ) {
+ RemoveEntryList (&Node2->Link);
+ gBS->ReinstallProtocolInterface (Node2->Handle, &gEfiShellProtocolGuid, NewShell, Node2->Interface);
+ FreePool (Node2);
}
} else {
//
// no need to restore
//
- Status = gBS->UninstallProtocolInterface(gImageHandle,
- &gEfiShellProtocolGuid,
- NewShell);
+ gBS->UninstallProtocolInterface (gImageHandle, &gEfiShellProtocolGuid, NewShell);
}
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup the shell environment.
+
+ @param[in, out] NewShell The pointer to the new shell protocol structure.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+CleanUpShellEnvironment (
+ IN OUT EFI_SHELL_PROTOCOL *NewShell
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
+
+ CleanUpShellProtocol (NewShell);
+
Status = gBS->CloseEvent(NewShell->ExecutionBreak);
NewShell->ExecutionBreak = NULL;
@@ -3666,28 +3741,27 @@ NotificationFunction(
if ( ((KeyData->Key.UnicodeChar == L'c') &&
(KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))) ||
(KeyData->Key.UnicodeChar == 3)
- ){
+ ){
if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {
return (EFI_UNSUPPORTED);
}
return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak));
} else if ((KeyData->Key.UnicodeChar == L's') &&
(KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))
- ){
+ ){
ShellInfoObject.HaltOutput = TRUE;
}
return (EFI_SUCCESS);
}
/**
- Function to start monitoring for CTRL-C using SimpleTextInputEx. This
+ Function to start monitoring for CTRL-C using SimpleTextInputEx. This
feature's enabled state was not known when the shell initially launched.
@retval EFI_SUCCESS The feature is enabled.
- @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory available.
**/
EFI_STATUS
-EFIAPI
InernalEfiShellStartMonitor(
VOID
)
@@ -3705,8 +3779,8 @@ InernalEfiShellStartMonitor(
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(Status)) {
ShellPrintHiiEx(
- -1,
- -1,
+ -1,
+ -1,
NULL,
STRING_TOKEN (STR_SHELL_NO_IN_EX),
ShellInfoObject.HiiHandle);
@@ -3727,7 +3801,7 @@ InernalEfiShellStartMonitor(
&KeyData,
NotificationFunction,
&ShellInfoObject.CtrlCNotifyHandle1);
-
+
KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
if (!EFI_ERROR(Status)) {
Status = SimpleEx->RegisterKeyNotify(