Member functions of EFI_SHELL_PROTOCOL and functions for creation,\r
manipulation, and initialization of EFI_SHELL_PROTOCOL.\r
\r
- Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2014, 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
EFI_STATUS Status;\r
CHAR16 *Temp;\r
\r
+ Status = EFI_SUCCESS;\r
DEBUG_CODE_BEGIN();\r
\r
if (Mapping != NULL) {\r
// append the path part onto the filepath.\r
//\r
ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
- PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L"\\", 1);\r
\r
AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\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
+\r
PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
FreePool(AlignedNode);\r
}\r
UINTN LoopVar;\r
CHAR16 *DeviceNameToReturn;\r
CHAR8 *Lang;\r
- CHAR8 *TempChar;\r
-\r
UINTN ParentControllerCount;\r
EFI_HANDLE *ParentControllerBuffer;\r
UINTN ParentDriverCount;\r
if (EFI_ERROR(Status)) {\r
continue;\r
}\r
- if (Language == NULL) {\r
- Lang = AllocateZeroPool(AsciiStrSize(CompName2->SupportedLanguages));\r
- if (Lang == NULL) {\r
- return (EFI_OUT_OF_RESOURCES);\r
- }\r
- AsciiStrCpy(Lang, CompName2->SupportedLanguages);\r
- TempChar = AsciiStrStr(Lang, ";");\r
- if (TempChar != NULL){\r
- *TempChar = CHAR_NULL;\r
- }\r
- } else {\r
- Lang = AllocateZeroPool(AsciiStrSize(Language));\r
- if (Lang == NULL) {\r
- return (EFI_OUT_OF_RESOURCES);\r
- }\r
- AsciiStrCpy(Lang, Language);\r
- }\r
+ Lang = GetBestLanguageForDriver(CompName2->SupportedLanguages, Language, FALSE);\r
Status = CompName2->GetControllerName(CompName2, DeviceHandle, NULL, Lang, &DeviceNameToReturn);\r
FreePool(Lang);\r
Lang = NULL;\r
if (EFI_ERROR(Status)) {\r
continue;\r
}\r
- if (Language == NULL) {\r
- Lang = AllocateZeroPool(AsciiStrSize(CompName2->SupportedLanguages));\r
- if (Lang == NULL) {\r
- return (EFI_OUT_OF_RESOURCES);\r
- }\r
- AsciiStrCpy(Lang, CompName2->SupportedLanguages);\r
- TempChar = AsciiStrStr(Lang, ";");\r
- if (TempChar != NULL){\r
- *TempChar = CHAR_NULL;\r
- }\r
- } else {\r
- Lang = AllocateZeroPool(AsciiStrSize(Language));\r
- if (Lang == NULL) {\r
- return (EFI_OUT_OF_RESOURCES);\r
- }\r
- AsciiStrCpy(Lang, Language);\r
- }\r
+ Lang = GetBestLanguageForDriver(CompName2->SupportedLanguages, Language, FALSE);\r
Status = CompName2->GetControllerName(CompName2, ParentControllerBuffer[LoopVar], DeviceHandle, Lang, &DeviceNameToReturn);\r
FreePool(Lang);\r
Lang = NULL;\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
+\r
+ @param[out] ExitDataSize ExitDataSize as returned from gBS->StartImage\r
+ @param[out] ExitData ExitData as returned from gBS->StartImage\r
\r
@retval EFI_SUCCESS The command executed successfully. The status code\r
returned by the command is pointed to by StatusCode.\r
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
IN CONST CHAR16 *CommandLine OPTIONAL,\r
IN CONST CHAR16 **Environment OPTIONAL,\r
- OUT EFI_STATUS *StatusCode OPTIONAL\r
+ OUT UINTN *ExitDataSize OPTIONAL,\r
+ OUT CHAR16 **ExitData OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_STATUS CleanupStatus;\r
EFI_HANDLE NewHandle;\r
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
LIST_ENTRY OrigEnvs;\r
EFI_SHELL_PARAMETERS_PROTOCOL ShellParamsProtocol;\r
+ UINTN InternalExitDataSize;\r
+ UINTN *ExitDataSizePtr;\r
+ CHAR16 *ImagePath;\r
+ UINTN Index;\r
+\r
+ // ExitDataSize is not OPTIONAL for gBS->BootServices, provide somewhere for\r
+ // it to be dumped if the caller doesn't want it.\r
+ if (ExitData == NULL) {\r
+ ExitDataSizePtr = &InternalExitDataSize;\r
+ } else {\r
+ ExitDataSizePtr = ExitDataSize;\r
+ }\r
\r
if (ParentImageHandle == NULL) {\r
return (EFI_INVALID_PARAMETER);\r
ShellParamsProtocol.StdErr = ShellInfoObject.NewShellParametersProtocol->StdErr;\r
Status = UpdateArgcArgv(&ShellParamsProtocol, CommandLine, NULL, NULL);\r
ASSERT_EFI_ERROR(Status);\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
+ // "The first entry in [Argv] is always the full file path of the\r
+ // executable" - UEFI Shell Spec section 2.3\r
+ //\r
+ ImagePath = EfiShellGetFilePathFromDevicePath (DevicePath);\r
+ // The image we're executing isn't necessarily in a filesystem - it might\r
+ // be memory mapped. In this case EfiShellGetFilePathFromDevicePath will\r
+ // return NULL, and we'll leave Argv[0] as UpdateArgcArgv set it.\r
+ if (ImagePath != NULL) {\r
+ if (ShellParamsProtocol.Argv == NULL) {\r
+ // Command line was empty or null.\r
+ // (UpdateArgcArgv sets Argv to NULL when CommandLine is "" or NULL)\r
+ ShellParamsProtocol.Argv = AllocatePool (sizeof (CHAR16 *));\r
+ if (ShellParamsProtocol.Argv == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto UnloadImage;\r
+ }\r
+ ShellParamsProtocol.Argc = 1;\r
+ } else {\r
+ // Free the string UpdateArgcArgv put in Argv[0];\r
+ FreePool (ShellParamsProtocol.Argv[0]);\r
+ }\r
+ ShellParamsProtocol.Argv[0] = ImagePath;\r
+ }\r
+\r
Status = gBS->InstallProtocolInterface(&NewHandle, &gEfiShellParametersProtocolGuid, EFI_NATIVE_INTERFACE, &ShellParamsProtocol);\r
ASSERT_EFI_ERROR(Status);\r
\r
///@todo initialize and install ShellInterface protocol on the new image for compatibility if - PcdGetBool(PcdShellSupportOldProtocols)\r
\r
//\r
- // now start the image and if the caller wanted the return code pass it to them...\r
+ // now start the image, passing up exit data if the caller requested it\r
//\r
if (!EFI_ERROR(Status)) {\r
- if (StatusCode != NULL) {\r
- *StatusCode = gBS->StartImage(NewHandle, NULL, NULL);\r
- } else {\r
- Status = gBS->StartImage(NewHandle, NULL, NULL);\r
+ Status = gBS->StartImage(\r
+ NewHandle,\r
+ ExitDataSizePtr,\r
+ ExitData\r
+ );\r
+\r
+ CleanupStatus = gBS->UninstallProtocolInterface(\r
+ NewHandle,\r
+ &gEfiShellParametersProtocolGuid,\r
+ &ShellParamsProtocol\r
+ );\r
+ ASSERT_EFI_ERROR(CleanupStatus);\r
+\r
+ goto FreeAlloc;\r
+ }\r
+\r
+UnloadImage:\r
+ // Unload image - We should only get here if we didn't call StartImage\r
+ gBS->UnloadImage (NewHandle);\r
+\r
+FreeAlloc:\r
+ // Free Argv (Allocated in UpdateArgcArgv)\r
+ if (ShellParamsProtocol.Argv != NULL) {\r
+ for (Index = 0; Index < ShellParamsProtocol.Argc; Index++) {\r
+ if (ShellParamsProtocol.Argv[Index] != NULL) {\r
+ FreePool (ShellParamsProtocol.Argv[Index]);\r
+ }\r
}\r
- }\r
-\r
- //\r
- // Cleanup (and dont overwrite errors)\r
- //\r
- if (EFI_ERROR(Status)) {\r
- gBS->UninstallProtocolInterface(NewHandle, &gEfiShellParametersProtocolGuid, &ShellParamsProtocol);\r
- } else {\r
- Status = gBS->UninstallProtocolInterface(NewHandle, &gEfiShellParametersProtocolGuid, &ShellParamsProtocol);\r
- ASSERT_EFI_ERROR(Status);\r
+ FreePool (ShellParamsProtocol.Argv);\r
}\r
}\r
\r
+ // Restore environment variables\r
if (!IsListEmpty(&OrigEnvs)) {\r
- if (EFI_ERROR(Status)) {\r
- SetEnvironmentVariableList(&OrigEnvs);\r
- } else {\r
- Status = SetEnvironmentVariableList(&OrigEnvs);\r
- }\r
+ CleanupStatus = SetEnvironmentVariableList(&OrigEnvs);\r
+ ASSERT_EFI_ERROR (CleanupStatus);\r
}\r
\r
return(Status);\r
CHAR16 *Temp;\r
EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
UINTN Size;\r
+ UINTN ExitDataSize;\r
+ CHAR16 *ExitData;\r
\r
if ((PcdGet8(PcdShellSupportLevel) < 1)) {\r
return (EFI_UNSUPPORTED);\r
DevPath,\r
Temp,\r
(CONST CHAR16**)Environment,\r
- StatusCode);\r
+ &ExitDataSize,\r
+ &ExitData);\r
+\r
+ if (Status == EFI_ABORTED) {\r
+ // If the command exited with an error, the shell should put the exit\r
+ // status in ExitData, preceded by a null-terminated string.\r
+ ASSERT (ExitDataSize == StrSize (ExitData) + sizeof (SHELL_STATUS));\r
+\r
+ if (StatusCode != NULL) {\r
+ // Skip the null-terminated string\r
+ ExitData += StrLen (ExitData) + 1;\r
+\r
+ // Use CopyMem to avoid alignment faults\r
+ CopyMem (StatusCode, ExitData, sizeof (SHELL_STATUS));\r
+\r
+ // Convert from SHELL_STATUS to EFI_STATUS\r
+ // EFI_STATUSes have top bit set when they are errors.\r
+ // (See UEFI Spec Appendix D)\r
+ if (*StatusCode != SHELL_SUCCESS) {\r
+ *StatusCode = (EFI_STATUS) *StatusCode | MAX_BIT;\r
+ }\r
+ }\r
+ FreePool (ExitData);\r
+ Status = EFI_SUCCESS;\r
+ } else if ((StatusCode != NULL) && !EFI_ERROR(Status)) {\r
+ *StatusCode = EFI_SUCCESS;\r
+ }\r
\r
//\r
// de-allocate and return\r
RemoveEntryList(&ShellFileListItem->Link);\r
InternalFreeShellFileInfoNode(ShellFileListItem);\r
}\r
+ InternalFreeShellFileInfoNode(*FileList);\r
+ *FileList = NULL;\r
return(EFI_SUCCESS);\r
}\r
\r
{\r
EFI_SHELL_FILE_INFO *ShellFileListItem;\r
EFI_SHELL_FILE_INFO *ShellFileListItem2;\r
+ EFI_SHELL_FILE_INFO *TempNode;\r
\r
if (FileList == NULL || *FileList == NULL) {\r
return (EFI_INVALID_PARAMETER);\r
(CHAR16*)ShellFileListItem->FullName,\r
(CHAR16*)ShellFileListItem2->FullName) == 0\r
){\r
+ TempNode = (EFI_SHELL_FILE_INFO *)GetPreviousNode(\r
+ &(*FileList)->Link,\r
+ &ShellFileListItem2->Link\r
+ );\r
RemoveEntryList(&ShellFileListItem2->Link);\r
InternalFreeShellFileInfoNode(ShellFileListItem2);\r
+ // Set ShellFileListItem2 to PreviousNode so we don't access Freed\r
+ // memory in GetNextNode in the loop expression above.\r
+ ShellFileListItem2 = TempNode;\r
}\r
}\r
}\r
return (EFI_SUCCESS);\r
}\r
+\r
+//\r
+// This is the same structure as the external version, but it has no CONST qualifiers.\r
+//\r
+typedef struct {\r
+ LIST_ENTRY Link; ///< Linked list members.\r
+ EFI_STATUS Status; ///< Status of opening the file. Valid only if Handle != NULL.\r
+ CHAR16 *FullName; ///< Fully qualified filename.\r
+ CHAR16 *FileName; ///< name of this file.\r
+ SHELL_FILE_HANDLE Handle; ///< Handle for interacting with the opened file or NULL if closed.\r
+ EFI_FILE_INFO *Info; ///< Pointer to the FileInfo struct for this file or NULL.\r
+} EFI_SHELL_FILE_INFO_NO_CONST;\r
+\r
/**\r
Allocates and duplicates a EFI_SHELL_FILE_INFO node.\r
\r
IN BOOLEAN Save\r
)\r
{\r
- EFI_SHELL_FILE_INFO *NewNode;\r
+ EFI_SHELL_FILE_INFO_NO_CONST *NewNode;\r
+\r
+ //\r
+ // try to confirm that the objects are in sync\r
+ //\r
+ ASSERT(sizeof(EFI_SHELL_FILE_INFO_NO_CONST) == sizeof(EFI_SHELL_FILE_INFO));\r
\r
NewNode = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
if (NewNode == NULL) {\r
if ( NewNode->FullName == NULL\r
|| NewNode->FileName == NULL\r
|| NewNode->Info == NULL\r
- ){\r
+ ){\r
+ SHELL_FREE_NON_NULL(NewNode->FullName);\r
+ SHELL_FREE_NON_NULL(NewNode->FileName);\r
+ SHELL_FREE_NON_NULL(NewNode->Info);\r
+ SHELL_FREE_NON_NULL(NewNode);\r
return(NULL);\r
}\r
NewNode->Status = Node->Status;\r
StrCpy((CHAR16*)NewNode->FileName, Node->FileName);\r
CopyMem(NewNode->Info, Node->Info, (UINTN)Node->Info->Size);\r
\r
- return(NewNode);\r
+ return((EFI_SHELL_FILE_INFO*)NewNode);\r
}\r
\r
/**\r
\r
@param[in] BasePath the Path to prepend onto filename for FullPath\r
@param[in] Status Status member initial value.\r
- @param[in] FullName FullName member initial value.\r
@param[in] FileName FileName member initial value.\r
@param[in] Handle Handle member initial value.\r
@param[in] Info Info struct to copy.\r
CreateAndPopulateShellFileInfo(\r
IN CONST CHAR16 *BasePath,\r
IN CONST EFI_STATUS Status,\r
- IN CONST CHAR16 *FullName,\r
IN CONST CHAR16 *FileName,\r
IN CONST SHELL_FILE_HANDLE Handle,\r
IN CONST EFI_FILE_INFO *Info\r
TempString = StrnCatGrow(&TempString, &Size, BasePath, 0);\r
if (TempString == NULL) {\r
FreePool((VOID*)ShellFileListItem->FileName);\r
- FreePool(ShellFileListItem->Info);\r
+ SHELL_FREE_NON_NULL(ShellFileListItem->Info);\r
FreePool(ShellFileListItem);\r
return (NULL);\r
}\r
Size = 0;\r
TempString = StrnCatGrow(&TempString, &Size, ShellFileHandleGetPath(FileDirHandle), 0);\r
if (TempString == NULL) {\r
+ SHELL_FREE_NON_NULL(BasePath);\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
TempSpot = StrStr(TempString, L";");\r
\r
TempString = StrnCatGrow(&TempString, &Size, BasePath, 0);\r
if (TempString == NULL) {\r
+ SHELL_FREE_NON_NULL(BasePath);\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
+ SHELL_FREE_NON_NULL(BasePath);\r
BasePath = TempString;\r
}\r
\r
; !EFI_ERROR(Status) && !NoFile\r
; Status = FileHandleFindNextFile(FileDirHandle, FileInfo, &NoFile)\r
){\r
- TempString = NULL;\r
- Size = 0;\r
//\r
// allocate a new EFI_SHELL_FILE_INFO and populate it...\r
//\r
- ASSERT((TempString == NULL && Size == 0) || (TempString != NULL));\r
- TempString = StrnCatGrow(&TempString, &Size, BasePath, 0);\r
- TempString = StrnCatGrow(&TempString, &Size, FileInfo->FileName, 0);\r
ShellFileListItem = CreateAndPopulateShellFileInfo(\r
BasePath,\r
- EFI_SUCCESS, // success since we didnt fail to open it...\r
- TempString,\r
+ EFI_SUCCESS, // success since we didnt fail to open it...\r
FileInfo->FileName,\r
- NULL, // no handle since not open\r
+ NULL, // no handle since not open\r
FileInfo);\r
\r
if (ShellFileList == NULL) {\r
EFI_SHELL_FILE_INFO *ShellInfo;\r
EFI_SHELL_FILE_INFO *ShellInfoNode;\r
EFI_SHELL_FILE_INFO *NewShellNode;\r
+ EFI_FILE_INFO *FileInfo;\r
BOOLEAN Directory;\r
CHAR16 *NewFullName;\r
UINTN Size;\r
\r
if (CurrentFilePattern[0] == CHAR_NULL\r
&&NextFilePatternStart[0] == CHAR_NULL\r
- ){\r
+ ){\r
//\r
- // Add the current parameter FileHandle to the list, then end...\r
+ // we want the parent or root node (if no parent)\r
//\r
if (ParentNode == NULL) {\r
- Status = EFI_INVALID_PARAMETER;\r
+ //\r
+ // We want the root node. create the node.\r
+ //\r
+ FileInfo = FileHandleGetInfo(FileHandle);\r
+ NewShellNode = CreateAndPopulateShellFileInfo(\r
+ L":",\r
+ EFI_SUCCESS,\r
+ L"\\",\r
+ FileHandle,\r
+ FileInfo\r
+ );\r
+ SHELL_FREE_NON_NULL(FileInfo);\r
} else {\r
+ //\r
+ // Add the current parameter FileHandle to the list, then end...\r
+ //\r
NewShellNode = InternalDuplicateShellFileInfo((EFI_SHELL_FILE_INFO*)ParentNode, TRUE);\r
- if (NewShellNode == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- } else {\r
- NewShellNode->Handle = NULL;\r
- if (*FileList == NULL) {\r
- *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
- InitializeListHead(&((*FileList)->Link));\r
- }\r
+ }\r
+ if (NewShellNode == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ NewShellNode->Handle = NULL;\r
+ if (*FileList == NULL) {\r
+ *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
+ InitializeListHead(&((*FileList)->Link));\r
+ }\r
\r
- //\r
- // Add to the returning to use list\r
- //\r
- InsertTailList(&(*FileList)->Link, &NewShellNode->Link);\r
+ //\r
+ // Add to the returning to use list\r
+ //\r
+ InsertTailList(&(*FileList)->Link, &NewShellNode->Link);\r
\r
- Status = EFI_SUCCESS;\r
- }\r
+ Status = EFI_SUCCESS;\r
}\r
} else {\r
Status = EfiShellFindFilesInDir(FileHandle, &ShellInfo);\r
)\r
{\r
CONST CHAR16 *ManFileName;\r
+ CHAR16 *FixCommand;\r
+ EFI_STATUS Status;\r
\r
ASSERT(HelpText != NULL);\r
+ FixCommand = NULL;\r
\r
ManFileName = ShellCommandGetManFileNameHandler(Command);\r
\r
if (ManFileName != NULL) {\r
return (ProcessManFile(ManFileName, Command, Sections, NULL, HelpText));\r
} else {\r
- return (ProcessManFile(Command, Command, Sections, NULL, HelpText));\r
+ if ((StrLen(Command)> 4)\r
+ && (Command[StrLen(Command)-1] == L'i' || Command[StrLen(Command)-1] == L'I')\r
+ && (Command[StrLen(Command)-2] == L'f' || Command[StrLen(Command)-2] == L'F')\r
+ && (Command[StrLen(Command)-3] == L'e' || Command[StrLen(Command)-3] == L'E')\r
+ && (Command[StrLen(Command)-4] == L'.')\r
+ ) {\r
+ FixCommand = AllocateZeroPool(StrSize(Command) - 4 * sizeof (CHAR16));\r
+ ASSERT(FixCommand != NULL);\r
+\r
+ StrnCpy(FixCommand, Command, StrLen(Command)-4);\r
+ Status = ProcessManFile(FixCommand, FixCommand, Sections, NULL, HelpText);\r
+ FreePool(FixCommand);\r
+ return Status;\r
+ } else {\r
+ return (ProcessManFile(Command, Command, Sections, NULL, HelpText));\r
+ }\r
}\r
}\r
\r
return (RetVal);\r
}\r
\r
+/**\r
+ Convert a null-terminated unicode string, in-place, to all lowercase.\r
+ Then return it.\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
+STATIC CHAR16 *\r
+ToLower (\r
+ CHAR16 *Str\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Str[Index] != L'\0'; Index++) {\r
+ if (Str[Index] >= L'A' && Str[Index] <= L'Z') {\r
+ Str[Index] -= (CHAR16)(L'A' - L'a');\r
+ }\r
+ }\r
+ return Str;\r
+}\r
+\r
/**\r
This function returns the command associated with a alias or a list of all\r
alias'.\r
UINTN RetSize;\r
UINT32 Attribs;\r
EFI_STATUS Status;\r
+ CHAR16 *AliasLower;\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
+\r
if (Volatile == NULL) {\r
- return (AddBufferToFreeList(GetVariable((CHAR16*)Alias, &gShellAliasGuid)));\r
+ return (AddBufferToFreeList(GetVariable(AliasLower, &gShellAliasGuid)));\r
}\r
RetSize = 0;\r
RetVal = NULL;\r
- Status = gRT->GetVariable((CHAR16*)Alias, &gShellAliasGuid, &Attribs, &RetSize, RetVal);\r
+ Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal);\r
if (Status == EFI_BUFFER_TOO_SMALL) {\r
RetVal = AllocateZeroPool(RetSize);\r
- Status = gRT->GetVariable((CHAR16*)Alias, &gShellAliasGuid, &Attribs, &RetSize, RetVal);\r
+ Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal);\r
}\r
if (EFI_ERROR(Status)) {\r
if (RetVal != NULL) {\r
*Volatile = TRUE;\r
}\r
\r
+ FreePool (AliasLower);\r
return (AddBufferToFreeList(RetVal));\r
}\r
return (AddBufferToFreeList(InternalEfiShellGetListAlias()));\r
IN BOOLEAN Volatile\r
)\r
{\r
+ EFI_STATUS Status;\r
+ CHAR16 *AliasLower;\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
//\r
// remove an alias (but passed in COMMAND parameter)\r
//\r
- return (gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL));\r
+ Status = (gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL));\r
} else {\r
//\r
// Add and replace are the same\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
\r
- return (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command));\r
+ Status = (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command));\r
}\r
+\r
+ if (Alias != NULL) {\r
+ FreePool (AliasLower);\r
+ }\r
+ return Status;\r
}\r
\r
/**\r
@retval EFI_NOT_FOUND the Alias intended to be deleted was not found\r
@retval EFI_ACCESS_DENIED The alias is a built-in alias or already existed and Replace was set to\r
FALSE.\r
+ @retval EFI_INVALID_PARAMETER Command is null or the empty string.\r
**/\r
EFI_STATUS\r
EFIAPI\r
IN BOOLEAN Volatile\r
)\r
{\r
- //\r
- // cant set over a built in alias\r
- //\r
if (ShellCommandIsOnAliasList(Alias==NULL?Command:Alias)) {\r
+ //\r
+ // cant set over a built in alias\r
+ //\r
return (EFI_ACCESS_DENIED);\r
- }\r
- if (Command == NULL || *Command == CHAR_NULL || StrLen(Command) == 0) {\r
+ } else if (Command == NULL || *Command == CHAR_NULL || StrLen(Command) == 0) {\r
+ //\r
+ // Command is null or empty\r
+ //\r
return (EFI_INVALID_PARAMETER);\r
- }\r
-\r
- if (EfiShellGetAlias(Command, NULL) != NULL && !Replace) {\r
+ } else if (EfiShellGetAlias(Command, NULL) != NULL && !Replace) {\r
+ //\r
+ // Alias already exists, Replace not set\r
+ //\r
return (EFI_ACCESS_DENIED);\r
+ } else {\r
+ return (InternalSetAlias(Command, Alias, Volatile));\r
}\r
-\r
- return (InternalSetAlias(Command, Alias, Volatile));\r
}\r
\r
// Pure FILE_HANDLE operations are passed to FileHandleLib\r
IN EFI_KEY_DATA *KeyData\r
)\r
{\r
- EFI_INPUT_KEY Key;\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
(KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))\r
){ \r
ShellInfoObject.HaltOutput = TRUE;\r
-\r
- //\r
- // Make sure that there are no pending keystrokes to pervent the pause.\r
- //\r
- gST->ConIn->Reset(gST->ConIn, FALSE);\r
- while (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key)==EFI_SUCCESS);\r
}\r
return (EFI_SUCCESS);\r
}\r
}\r
return (Status);\r
}\r
+\r