/** @file\r
Provides interface to shell functionality for shell commands and applications.\r
\r
- Copyright (c) 2006 - 2010, 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 2016-2018 Dell Technologies.<BR>\r
+ Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "UefiShellLib.h"\r
-\r
-#define MAX_FILE_NAME_LEN 522 // (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)\r
-#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)\r
+#include <Library/SortLib.h>\r
+#include <Library/BaseLib.h>\r
\r
//\r
-// This is not static since it's extern in the .h file\r
+// globals...\r
//\r
SHELL_PARAM_ITEM EmptyParamList[] = {\r
{NULL, TypeMax}\r
};\r
+SHELL_PARAM_ITEM SfoParamList[] = {\r
+ {L"-sfo", TypeFlag},\r
+ {NULL, TypeMax}\r
+ };\r
+EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;\r
+EFI_SHELL_INTERFACE *mEfiShellInterface;\r
+EFI_SHELL_PROTOCOL *gEfiShellProtocol;\r
+EFI_SHELL_PARAMETERS_PROTOCOL *gEfiShellParametersProtocol;\r
+EFI_HANDLE mEfiShellEnvironment2Handle;\r
+FILE_HANDLE_FUNCTION_MAP FileFunctionMap;\r
+EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollationProtocol;\r
\r
-//\r
-// Static file globals for the shell library\r
-//\r
-STATIC EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;\r
-STATIC EFI_SHELL_INTERFACE *mEfiShellInterface;\r
-STATIC EFI_SHELL_PROTOCOL *mEfiShellProtocol;\r
-STATIC EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol;\r
-STATIC EFI_HANDLE mEfiShellEnvironment2Handle;\r
-STATIC FILE_HANDLE_FUNCTION_MAP FileFunctionMap;\r
-STATIC UINTN mTotalParameterCount;\r
-STATIC CHAR16 *mPostReplaceFormat;\r
-STATIC CHAR16 *mPostReplaceFormat2;\r
+/**\r
+ Return a clean, fully-qualified version of an input path. If the return value\r
+ is non-NULL the caller must free the memory when it is no longer needed.\r
+\r
+ If asserts are disabled, and if the input parameter is NULL, NULL is returned.\r
+\r
+ If there is not enough memory available to create the fully-qualified path or\r
+ a copy of the input path, NULL is returned.\r
+\r
+ If there is no working directory, a clean copy of Path is returned.\r
+\r
+ Otherwise, the current file system or working directory (as appropriate) is\r
+ prepended to Path and the resulting path is cleaned and returned.\r
+\r
+ NOTE: If the input path is an empty string, then the current working directory\r
+ (if it exists) is returned. In other words, an empty input path is treated\r
+ exactly the same as ".".\r
+\r
+ @param[in] Path A pointer to some file or directory path.\r
+\r
+ @retval NULL The input path is NULL or out of memory.\r
+\r
+ @retval non-NULL A pointer to a clean, fully-qualified version of Path.\r
+ If there is no working directory, then a pointer to a\r
+ clean, but not necessarily fully-qualified version of\r
+ Path. The caller must free this memory when it is no\r
+ longer needed.\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+FullyQualifyPath(\r
+ IN CONST CHAR16 *Path\r
+ )\r
+{\r
+ CONST CHAR16 *WorkingPath;\r
+ CONST CHAR16 *InputPath;\r
+ CHAR16 *CharPtr;\r
+ CHAR16 *InputFileSystem;\r
+ UINTN FileSystemCharCount;\r
+ CHAR16 *FullyQualifiedPath;\r
+ UINTN Size;\r
+\r
+ FullyQualifiedPath = NULL;\r
+\r
+ ASSERT(Path != NULL);\r
+ //\r
+ // Handle erroneous input when asserts are disabled.\r
+ //\r
+ if (Path == NULL) {\r
+ return NULL;\r
+ }\r
+ //\r
+ // In paths that contain ":", like fs0:dir/file.ext and fs2:\fqpath\file.ext,\r
+ // we have to consider the file system part separately from the "path" part.\r
+ // If there is a file system in the path, we have to get the current working\r
+ // directory for that file system. Then we need to use the part of the path\r
+ // following the ":". If a path does not contain ":", we use it as given.\r
+ //\r
+ InputPath = StrStr(Path, L":");\r
+ if (InputPath != NULL) {\r
+ InputPath++;\r
+ FileSystemCharCount = ((UINTN)InputPath - (UINTN)Path + sizeof(CHAR16)) / sizeof(CHAR16);\r
+ InputFileSystem = AllocateCopyPool(FileSystemCharCount * sizeof(CHAR16), Path);\r
+ if (InputFileSystem != NULL) {\r
+ InputFileSystem[FileSystemCharCount - 1] = CHAR_NULL;\r
+ }\r
+ WorkingPath = ShellGetCurrentDir(InputFileSystem);\r
+ SHELL_FREE_NON_NULL(InputFileSystem);\r
+ } else {\r
+ InputPath = Path;\r
+ WorkingPath = ShellGetEnvironmentVariable(L"cwd");\r
+ }\r
+\r
+ if (WorkingPath == NULL) {\r
+ //\r
+ // With no working directory, all we can do is copy and clean the input path.\r
+ //\r
+ FullyQualifiedPath = AllocateCopyPool(StrSize(Path), Path);\r
+ } else {\r
+ //\r
+ // Allocate space for both strings plus one more character.\r
+ //\r
+ Size = StrSize(WorkingPath) + StrSize(InputPath);\r
+ FullyQualifiedPath = AllocateZeroPool(Size);\r
+ if (FullyQualifiedPath == NULL) {\r
+ //\r
+ // Try to copy and clean just the input. No harm if not enough memory.\r
+ //\r
+ FullyQualifiedPath = AllocateCopyPool(StrSize(Path), Path);\r
+ } else {\r
+ if (*InputPath == L'\\' || *InputPath == L'/') {\r
+ //\r
+ // Absolute path: start with the current working directory, then\r
+ // truncate the new path after the file system part.\r
+ //\r
+ StrCpyS(FullyQualifiedPath, Size/sizeof(CHAR16), WorkingPath);\r
+ CharPtr = StrStr(FullyQualifiedPath, L":");\r
+ if (CharPtr != NULL) {\r
+ *(CharPtr + 1) = CHAR_NULL;\r
+ }\r
+ } else {\r
+ //\r
+ // Relative path: start with the working directory and append "\".\r
+ //\r
+ StrCpyS(FullyQualifiedPath, Size/sizeof(CHAR16), WorkingPath);\r
+ StrCatS(FullyQualifiedPath, Size/sizeof(CHAR16), L"\\");\r
+ }\r
+ //\r
+ // Now append the absolute or relative path.\r
+ //\r
+ StrCatS(FullyQualifiedPath, Size/sizeof(CHAR16), InputPath);\r
+ }\r
+ }\r
+\r
+ PathCleanUpDirectories(FullyQualifiedPath);\r
+\r
+ return FullyQualifiedPath;\r
+}\r
\r
/**\r
Check if a Unicode character is a hexadecimal character.\r
\r
This internal function checks if a Unicode character is a\r
- decimal character. The valid hexadecimal character is\r
+ numeric character. The valid hexadecimal characters are\r
L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
\r
-\r
@param Char The character to check against.\r
\r
@retval TRUE If the Char is a hexadecmial character.\r
EFIAPI\r
ShellIsHexaDecimalDigitCharacter (\r
IN CHAR16 Char\r
- ) {\r
+ )\r
+{\r
return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));\r
}\r
\r
/**\r
- helper function to find ShellEnvironment2 for constructor\r
+ Check if a Unicode character is a decimal character.\r
+\r
+ This internal function checks if a Unicode character is a\r
+ decimal character. The valid characters are\r
+ L'0' to L'9'.\r
+\r
+\r
+ @param Char The character to check against.\r
+\r
+ @retval TRUE If the Char is a hexadecmial character.\r
+ @retval FALSE If the Char is not a hexadecmial character.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ShellIsDecimalDigitCharacter (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ return (BOOLEAN) (Char >= L'0' && Char <= L'9');\r
+}\r
+\r
+/**\r
+ Helper function to find ShellEnvironment2 for constructor.\r
+\r
+ @param[in] ImageHandle A copy of the calling image's handle.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
**/\r
EFI_STATUS\r
-EFIAPI\r
ShellFindSE2 (\r
IN EFI_HANDLE ImageHandle\r
- ) {\r
+ )\r
+{\r
EFI_STATUS Status;\r
EFI_HANDLE *Buffer;\r
UINTN BufferSize;\r
ImageHandle,\r
NULL,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
+ );\r
//\r
// look for the mEfiShellEnvironment2 protocol at a higher level\r
//\r
- if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE)){\r
+ if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid))){\r
//\r
// figure out how big of a buffer we need.\r
//\r
NULL, // ignored for ByProtocol\r
&BufferSize,\r
Buffer\r
- );\r
+ );\r
//\r
// maybe it's not there???\r
//\r
if (Status == EFI_BUFFER_TOO_SMALL) {\r
- Buffer = (EFI_HANDLE*)AllocatePool(BufferSize);\r
- ASSERT(Buffer != NULL);\r
+ Buffer = (EFI_HANDLE*)AllocateZeroPool(BufferSize);\r
+ if (Buffer == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
Status = gBS->LocateHandle (ByProtocol,\r
&gEfiShellEnvironment2Guid,\r
NULL, // ignored for ByProtocol\r
&BufferSize,\r
Buffer\r
- );\r
+ );\r
}\r
if (!EFI_ERROR (Status) && Buffer != NULL) {\r
//\r
ImageHandle,\r
NULL,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE) {\r
+ );\r
+ if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid)) {\r
mEfiShellEnvironment2Handle = Buffer[HandleIndex];\r
Status = EFI_SUCCESS;\r
break;\r
return (Status);\r
}\r
\r
+/**\r
+ Function to do most of the work of the constructor. Allows for calling\r
+ multiple times without complete re-initialization.\r
+\r
+ @param[in] ImageHandle A copy of the ImageHandle.\r
+ @param[in] SystemTable A pointer to the SystemTable for the application.\r
+\r
+ @retval EFI_SUCCESS The operationw as successful.\r
+**/\r
EFI_STATUS\r
-EFIAPI\r
ShellLibConstructorWorker (\r
IN EFI_HANDLE ImageHandle,\r
IN EFI_SYSTEM_TABLE *SystemTable\r
- ) {\r
- EFI_STATUS Status;\r
-\r
- mPostReplaceFormat = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
- ASSERT (mPostReplaceFormat != NULL);\r
- mPostReplaceFormat2 = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
- ASSERT (mPostReplaceFormat2 != NULL);\r
-\r
- //\r
- // Set the parameter count to an invalid number\r
- //\r
- mTotalParameterCount = (UINTN)(-1);\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
\r
- //\r
- // UEFI 2.0 shell interfaces (used preferentially)\r
- //\r
- Status = gBS->OpenProtocol(ImageHandle,\r
- &gEfiShellProtocolGuid,\r
- (VOID **)&mEfiShellProtocol,\r
- ImageHandle,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR(Status)) {\r
- mEfiShellProtocol = NULL;\r
+ if (gEfiShellProtocol == NULL) {\r
+ //\r
+ // UEFI 2.0 shell interfaces (used preferentially)\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ImageHandle,\r
+ &gEfiShellProtocolGuid,\r
+ (VOID **)&gEfiShellProtocol,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Search for the shell protocol\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiShellProtocolGuid,\r
+ NULL,\r
+ (VOID **)&gEfiShellProtocol\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gEfiShellProtocol = NULL;\r
+ }\r
+ }\r
}\r
- Status = gBS->OpenProtocol(ImageHandle,\r
- &gEfiShellParametersProtocolGuid,\r
- (VOID **)&mEfiShellParametersProtocol,\r
- ImageHandle,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR(Status)) {\r
- mEfiShellParametersProtocol = NULL;\r
+\r
+ if (gEfiShellParametersProtocol == NULL) {\r
+ Status = gBS->OpenProtocol (\r
+ ImageHandle,\r
+ &gEfiShellParametersProtocolGuid,\r
+ (VOID **)&gEfiShellParametersProtocol,\r
+ ImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gEfiShellParametersProtocol = NULL;\r
+ }\r
}\r
\r
- if (mEfiShellParametersProtocol == NULL || mEfiShellProtocol == NULL) {\r
+ if (gEfiShellProtocol == NULL) {\r
//\r
// Moved to seperate function due to complexity\r
//\r
ImageHandle,\r
NULL,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
+ );\r
if (EFI_ERROR(Status)) {\r
mEfiShellInterface = NULL;\r
}\r
}\r
+\r
//\r
- // only success getting 2 of either the old or new, but no 1/2 and 1/2\r
+ // Getting either EDK Shell's ShellEnvironment2 and ShellInterface protocol\r
+ // or UEFI Shell's Shell protocol.\r
+ // When ShellLib is linked to a driver producing DynamicCommand protocol,\r
+ // ShellParameters protocol is set by DynamicCommand.Handler().\r
//\r
- if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) ||\r
- (mEfiShellProtocol != NULL && mEfiShellParametersProtocol != NULL) ) {\r
- if (mEfiShellProtocol != NULL) {\r
- FileFunctionMap.GetFileInfo = mEfiShellProtocol->GetFileInfo;\r
- FileFunctionMap.SetFileInfo = mEfiShellProtocol->SetFileInfo;\r
- FileFunctionMap.ReadFile = mEfiShellProtocol->ReadFile;\r
- FileFunctionMap.WriteFile = mEfiShellProtocol->WriteFile;\r
- FileFunctionMap.CloseFile = mEfiShellProtocol->CloseFile;\r
- FileFunctionMap.DeleteFile = mEfiShellProtocol->DeleteFile;\r
- FileFunctionMap.GetFilePosition = mEfiShellProtocol->GetFilePosition;\r
- FileFunctionMap.SetFilePosition = mEfiShellProtocol->SetFilePosition;\r
- FileFunctionMap.FlushFile = mEfiShellProtocol->FlushFile;\r
- FileFunctionMap.GetFileSize = mEfiShellProtocol->GetFileSize;\r
+ if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) ||\r
+ (gEfiShellProtocol != NULL)\r
+ ) {\r
+ if (gEfiShellProtocol != NULL) {\r
+ FileFunctionMap.GetFileInfo = gEfiShellProtocol->GetFileInfo;\r
+ FileFunctionMap.SetFileInfo = gEfiShellProtocol->SetFileInfo;\r
+ FileFunctionMap.ReadFile = gEfiShellProtocol->ReadFile;\r
+ FileFunctionMap.WriteFile = gEfiShellProtocol->WriteFile;\r
+ FileFunctionMap.CloseFile = gEfiShellProtocol->CloseFile;\r
+ FileFunctionMap.DeleteFile = gEfiShellProtocol->DeleteFile;\r
+ FileFunctionMap.GetFilePosition = gEfiShellProtocol->GetFilePosition;\r
+ FileFunctionMap.SetFilePosition = gEfiShellProtocol->SetFilePosition;\r
+ FileFunctionMap.FlushFile = gEfiShellProtocol->FlushFile;\r
+ FileFunctionMap.GetFileSize = gEfiShellProtocol->GetFileSize;\r
} else {\r
- FileFunctionMap.GetFileInfo = FileHandleGetInfo;\r
- FileFunctionMap.SetFileInfo = FileHandleSetInfo;\r
- FileFunctionMap.ReadFile = FileHandleRead;\r
- FileFunctionMap.WriteFile = FileHandleWrite;\r
- FileFunctionMap.CloseFile = FileHandleClose;\r
- FileFunctionMap.DeleteFile = FileHandleDelete;\r
- FileFunctionMap.GetFilePosition = FileHandleGetPosition;\r
- FileFunctionMap.SetFilePosition = FileHandleSetPosition;\r
- FileFunctionMap.FlushFile = FileHandleFlush;\r
- FileFunctionMap.GetFileSize = FileHandleGetSize;\r
+ FileFunctionMap.GetFileInfo = (EFI_SHELL_GET_FILE_INFO)FileHandleGetInfo;\r
+ FileFunctionMap.SetFileInfo = (EFI_SHELL_SET_FILE_INFO)FileHandleSetInfo;\r
+ FileFunctionMap.ReadFile = (EFI_SHELL_READ_FILE)FileHandleRead;\r
+ FileFunctionMap.WriteFile = (EFI_SHELL_WRITE_FILE)FileHandleWrite;\r
+ FileFunctionMap.CloseFile = (EFI_SHELL_CLOSE_FILE)FileHandleClose;\r
+ FileFunctionMap.DeleteFile = (EFI_SHELL_DELETE_FILE)FileHandleDelete;\r
+ FileFunctionMap.GetFilePosition = (EFI_SHELL_GET_FILE_POSITION)FileHandleGetPosition;\r
+ FileFunctionMap.SetFilePosition = (EFI_SHELL_SET_FILE_POSITION)FileHandleSetPosition;\r
+ FileFunctionMap.FlushFile = (EFI_SHELL_FLUSH_FILE)FileHandleFlush;\r
+ FileFunctionMap.GetFileSize = (EFI_SHELL_GET_FILE_SIZE)FileHandleGetSize;\r
}\r
return (EFI_SUCCESS);\r
}\r
ShellLibConstructor (\r
IN EFI_HANDLE ImageHandle,\r
IN EFI_SYSTEM_TABLE *SystemTable\r
- ) {\r
-\r
-\r
+ )\r
+{\r
mEfiShellEnvironment2 = NULL;\r
- mEfiShellProtocol = NULL;\r
- mEfiShellParametersProtocol = NULL;\r
+ gEfiShellProtocol = NULL;\r
+ gEfiShellParametersProtocol = NULL;\r
mEfiShellInterface = NULL;\r
mEfiShellEnvironment2Handle = NULL;\r
- mPostReplaceFormat = NULL;\r
- mPostReplaceFormat2 = NULL;\r
+ mUnicodeCollationProtocol = NULL;\r
\r
//\r
// verify that auto initialize is not set false\r
}\r
\r
/**\r
- Destructory for the library. free any resources.\r
+ Destructor for the library. free any resources.\r
+\r
+ @param[in] ImageHandle A copy of the ImageHandle.\r
+ @param[in] SystemTable A pointer to the SystemTable for the application.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+ @return An error from the CloseProtocol function.\r
**/\r
EFI_STATUS\r
EFIAPI\r
ShellLibDestructor (\r
IN EFI_HANDLE ImageHandle,\r
IN EFI_SYSTEM_TABLE *SystemTable\r
- ) {\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
if (mEfiShellEnvironment2 != NULL) {\r
- gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,\r
+ Status = gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,\r
&gEfiShellEnvironment2Guid,\r
ImageHandle,\r
NULL);\r
- mEfiShellEnvironment2 = NULL;\r
+ if (!EFI_ERROR (Status)) {\r
+ mEfiShellEnvironment2 = NULL;\r
+ mEfiShellEnvironment2Handle = NULL;\r
+ }\r
}\r
if (mEfiShellInterface != NULL) {\r
- gBS->CloseProtocol(ImageHandle,\r
+ Status = gBS->CloseProtocol(ImageHandle,\r
&gEfiShellInterfaceGuid,\r
ImageHandle,\r
NULL);\r
- mEfiShellInterface = NULL;\r
+ if (!EFI_ERROR (Status)) {\r
+ mEfiShellInterface = NULL;\r
+ }\r
}\r
- if (mEfiShellProtocol != NULL) {\r
- gBS->CloseProtocol(ImageHandle,\r
+ if (gEfiShellProtocol != NULL) {\r
+ Status = gBS->CloseProtocol(ImageHandle,\r
&gEfiShellProtocolGuid,\r
ImageHandle,\r
NULL);\r
- mEfiShellProtocol = NULL;\r
+ if (!EFI_ERROR (Status)) {\r
+ gEfiShellProtocol = NULL;\r
+ }\r
}\r
- if (mEfiShellParametersProtocol != NULL) {\r
- gBS->CloseProtocol(ImageHandle,\r
+ if (gEfiShellParametersProtocol != NULL) {\r
+ Status = gBS->CloseProtocol(ImageHandle,\r
&gEfiShellParametersProtocolGuid,\r
ImageHandle,\r
NULL);\r
- mEfiShellParametersProtocol = NULL;\r
- }\r
- mEfiShellEnvironment2Handle = NULL;\r
-\r
- if (mPostReplaceFormat != NULL) {\r
- FreePool(mPostReplaceFormat);\r
- }\r
- if (mPostReplaceFormat2 != NULL) {\r
- FreePool(mPostReplaceFormat2);\r
+ if (!EFI_ERROR (Status)) {\r
+ gEfiShellParametersProtocol = NULL;\r
+ }\r
}\r
- mPostReplaceFormat = NULL;\r
- mPostReplaceFormat2 = NULL;\r
\r
return (EFI_SUCCESS);\r
}\r
EFI_STATUS\r
EFIAPI\r
ShellInitialize (\r
- ) {\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
//\r
// if auto initialize is not false then skip\r
//\r
//\r
// deinit the current stuff\r
//\r
- ASSERT_EFI_ERROR(ShellLibDestructor(gImageHandle, gST));\r
+ Status = ShellLibDestructor (gImageHandle, gST);\r
+ ASSERT_EFI_ERROR (Status);\r
\r
//\r
// init the new stuff\r
EFI_FILE_INFO*\r
EFIAPI\r
ShellGetFileInfo (\r
- IN EFI_FILE_HANDLE FileHandle\r
- ) {\r
+ IN SHELL_FILE_HANDLE FileHandle\r
+ )\r
+{\r
return (FileFunctionMap.GetFileInfo(FileHandle));\r
}\r
\r
/**\r
- This function will set the information about the file for the opened handle\r
+ This function sets the information about the file for the opened handle\r
specified.\r
\r
- @param FileHandle The file handle of the file for which information\r
- is being set\r
+ @param[in] FileHandle The file handle of the file for which information\r
+ is being set.\r
\r
- @param FileInfo The infotmation to set.\r
+ @param[in] FileInfo The information to set.\r
\r
- @retval EFI_SUCCESS The information was set.\r
- @retval EFI_UNSUPPORTED The InformationType is not known.\r
- @retval EFI_NO_MEDIA The device has no medium.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
- @retval EFI_ACCESS_DENIED The file was opened read only.\r
- @retval EFI_VOLUME_FULL The volume is full.\r
+ @retval EFI_SUCCESS The information was set.\r
+ @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid.\r
+ @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo.\r
+ @retval EFI_NO_MEDIA The device has no medium.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
**/\r
EFI_STATUS\r
EFIAPI\r
ShellSetFileInfo (\r
- IN EFI_FILE_HANDLE FileHandle,\r
+ IN SHELL_FILE_HANDLE FileHandle,\r
IN EFI_FILE_INFO *FileInfo\r
- ) {\r
+ )\r
+{\r
return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo));\r
}\r
\r
This function opens a file with the open mode according to the file path. The\r
Attributes is valid only for EFI_FILE_MODE_CREATE.\r
\r
- @param FilePath on input the device path to the file. On output\r
+ @param FilePath on input the device path to the file. On output\r
the remaining device path.\r
- @param DeviceHandle pointer to the system device handle.\r
- @param FileHandle pointer to the file handle.\r
- @param OpenMode the mode to open the file with.\r
- @param Attributes the file's file attributes.\r
-\r
- @retval EFI_SUCCESS The information was set.\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\r
+ @param FileHandle pointer to the file handle.\r
+ @param OpenMode the mode to open the file with.\r
+ @param Attributes the file's file attributes.\r
+\r
+ @retval EFI_SUCCESS The information was set.\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\r
device or the file system could not be found on\r
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\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\r
medium is no longer supported.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
- @retval EFI_ACCESS_DENIED The file was opened read only.\r
- @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
file.\r
- @retval EFI_VOLUME_FULL The volume is full.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
**/\r
EFI_STATUS\r
EFIAPI\r
ShellOpenFileByDevicePath(\r
- IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
- OUT EFI_HANDLE *DeviceHandle,\r
- OUT EFI_FILE_HANDLE *FileHandle,\r
- IN UINT64 OpenMode,\r
- IN UINT64 Attributes\r
- ) {\r
- CHAR16 *FileName;\r
- EFI_STATUS Status;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
- EFI_FILE_HANDLE LastHandle;\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
+ OUT SHELL_FILE_HANDLE *FileHandle,\r
+ IN UINT64 OpenMode,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ CHAR16 *FileName;\r
+ EFI_STATUS Status;\r
+ EFI_FILE_PROTOCOL *File;\r
+\r
+ if (FilePath == NULL || FileHandle == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
\r
- //\r
- // ASERT for FileHandle, FilePath, and DeviceHandle being NULL\r
- //\r
- ASSERT(FilePath != NULL);\r
- ASSERT(FileHandle != NULL);\r
- ASSERT(DeviceHandle != NULL);\r
//\r
// which shell interface should we use\r
//\r
- if (mEfiShellProtocol != NULL) {\r
+ if (gEfiShellProtocol != NULL) {\r
//\r
// use UEFI Shell 2.0 method.\r
//\r
- FileName = mEfiShellProtocol->GetFilePathFromDevicePath(*FilePath);\r
+ FileName = gEfiShellProtocol->GetFilePathFromDevicePath(*FilePath);\r
if (FileName == NULL) {\r
return (EFI_INVALID_PARAMETER);\r
}\r
//\r
// use old shell method.\r
//\r
- Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid,\r
- FilePath,\r
- DeviceHandle);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- Status = gBS->OpenProtocol(*DeviceHandle,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- (VOID**)&EfiSimpleFileSystemProtocol,\r
- gImageHandle,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+ Status = EfiOpenFileByDevicePath (FilePath, &File, OpenMode, Attributes);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, FileHandle);\r
- if (EFI_ERROR (Status)) {\r
- FileHandle = NULL;\r
- return Status;\r
- }\r
\r
//\r
- // go down directories one node at a time.\r
+ // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!\r
//\r
- while (!IsDevicePathEnd (*FilePath)) {\r
- //\r
- // For file system access each node should be a file path component\r
- //\r
- if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||\r
- DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP\r
- ) {\r
- FileHandle = NULL;\r
- return (EFI_INVALID_PARAMETER);\r
- }\r
- //\r
- // Open this file path node\r
- //\r
- LastHandle = *FileHandle;\r
- *FileHandle = NULL;\r
-\r
- //\r
- // Try to test opening an existing file\r
- //\r
- Status = LastHandle->Open (\r
- LastHandle,\r
- FileHandle,\r
- ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
- OpenMode &~EFI_FILE_MODE_CREATE,\r
- 0\r
- );\r
-\r
- //\r
- // see if the error was that it needs to be created\r
- //\r
- if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {\r
- Status = LastHandle->Open (\r
- LastHandle,\r
- FileHandle,\r
- ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,\r
- OpenMode,\r
- Attributes\r
- );\r
- }\r
- //\r
- // Close the last node\r
- //\r
- LastHandle->Close (LastHandle);\r
-\r
- if (EFI_ERROR(Status)) {\r
- return (Status);\r
- }\r
-\r
- //\r
- // Get the next node\r
- //\r
- *FilePath = NextDevicePathNode (*FilePath);\r
- }\r
+ *FileHandle = (VOID*)File;\r
return (EFI_SUCCESS);\r
}\r
\r
otherwise, the Filehandle is NULL. The Attributes is valid only for\r
EFI_FILE_MODE_CREATE.\r
\r
- if FileNAme is NULL then ASSERT()\r
+ if FileName is NULL then ASSERT()\r
\r
- @param FileName pointer to file name\r
- @param FileHandle pointer to the file handle.\r
- @param OpenMode the mode to open the file with.\r
- @param Attributes the file's file attributes.\r
+ @param FileName pointer to file name\r
+ @param FileHandle pointer to the file handle.\r
+ @param OpenMode the mode to open the file with.\r
+ @param Attributes the file's file attributes.\r
\r
- @retval EFI_SUCCESS The information was set.\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\r
+ @retval EFI_SUCCESS The information was set.\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\r
device or the file system could not be found\r
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\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\r
medium is no longer supported.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
- @retval EFI_ACCESS_DENIED The file was opened read only.\r
- @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
file.\r
- @retval EFI_VOLUME_FULL The volume is full.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
**/\r
EFI_STATUS\r
EFIAPI\r
ShellOpenFileByName(\r
- IN CONST CHAR16 *FileName,\r
- OUT EFI_FILE_HANDLE *FileHandle,\r
+ IN CONST CHAR16 *FileName,\r
+ OUT SHELL_FILE_HANDLE *FileHandle,\r
IN UINT64 OpenMode,\r
- IN UINT64 Attributes\r
- ) {\r
- EFI_HANDLE DeviceHandle;\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
EFI_STATUS Status;\r
EFI_FILE_INFO *FileInfo;\r
+ CHAR16 *FileNameCopy;\r
+ EFI_STATUS Status2;\r
\r
//\r
// ASSERT if FileName is NULL\r
//\r
ASSERT(FileName != NULL);\r
\r
- if (mEfiShellProtocol != NULL) {\r
+ if (FileName == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
+ if (gEfiShellProtocol != NULL) {\r
+ if ((OpenMode & EFI_FILE_MODE_CREATE) == EFI_FILE_MODE_CREATE) {\r
+\r
+ //\r
+ // Create only a directory\r
+ //\r
+ if ((Attributes & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {\r
+ return ShellCreateDirectory(FileName, FileHandle);\r
+ }\r
+\r
+ //\r
+ // Create the directory to create the file in\r
+ //\r
+ FileNameCopy = AllocateCopyPool (StrSize (FileName), FileName);\r
+ if (FileNameCopy == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ PathCleanUpDirectories (FileNameCopy);\r
+ if (PathRemoveLastItem (FileNameCopy)) {\r
+ if (!EFI_ERROR(ShellCreateDirectory (FileNameCopy, FileHandle))) {\r
+ ShellCloseFile (FileHandle);\r
+ }\r
+ }\r
+ SHELL_FREE_NON_NULL (FileNameCopy);\r
+ }\r
+\r
//\r
- // Use UEFI Shell 2.0 method\r
+ // Use UEFI Shell 2.0 method to create the file\r
//\r
- Status = mEfiShellProtocol->OpenFileByName(FileName,\r
+ Status = gEfiShellProtocol->OpenFileByName(FileName,\r
FileHandle,\r
OpenMode);\r
- if (!EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (mUnicodeCollationProtocol == NULL) {\r
+ Status = gBS->LocateProtocol (&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&mUnicodeCollationProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ gEfiShellProtocol->CloseFile (*FileHandle);\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ if ((mUnicodeCollationProtocol->StriColl (mUnicodeCollationProtocol, (CHAR16*)FileName, L"NUL") != 0) &&\r
+ (mUnicodeCollationProtocol->StriColl (mUnicodeCollationProtocol, (CHAR16*)FileName, L"NULL") != 0) &&\r
+ !EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){\r
FileInfo = FileFunctionMap.GetFileInfo(*FileHandle);\r
ASSERT(FileInfo != NULL);\r
FileInfo->Attribute = Attributes;\r
- Status = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);\r
+ Status2 = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);\r
FreePool(FileInfo);\r
+ if (EFI_ERROR (Status2)) {\r
+ gEfiShellProtocol->CloseFile(*FileHandle);\r
+ }\r
+ Status = Status2;\r
}\r
return (Status);\r
}\r
//\r
ASSERT(mEfiShellEnvironment2 != NULL);\r
FilePath = mEfiShellEnvironment2->NameToPath ((CHAR16*)FileName);\r
- if (FileDevicePath != NULL) {\r
+ if (FilePath != NULL) {\r
return (ShellOpenFileByDevicePath(&FilePath,\r
- &DeviceHandle,\r
FileHandle,\r
OpenMode,\r
- Attributes ));\r
+ Attributes));\r
}\r
return (EFI_DEVICE_ERROR);\r
}\r
otherwise, the Filehandle is NULL. If the directory already existed, this\r
function opens the existing directory.\r
\r
- @param DirectoryName pointer to directory name\r
- @param FileHandle pointer to the file handle.\r
+ @param DirectoryName pointer to directory name\r
+ @param FileHandle pointer to the file handle.\r
\r
- @retval EFI_SUCCESS The information was set.\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\r
+ @retval EFI_SUCCESS The information was set.\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\r
device or the file system could not be found\r
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\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\r
medium is no longer supported.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
- @retval EFI_ACCESS_DENIED The file was opened read only.\r
- @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
file.\r
- @retval EFI_VOLUME_FULL The volume is full.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
@sa ShellOpenFileByName\r
**/\r
EFI_STATUS\r
EFIAPI\r
ShellCreateDirectory(\r
IN CONST CHAR16 *DirectoryName,\r
- OUT EFI_FILE_HANDLE *FileHandle\r
- ) {\r
- if (mEfiShellProtocol != NULL) {\r
+ OUT SHELL_FILE_HANDLE *FileHandle\r
+ )\r
+{\r
+ if (gEfiShellProtocol != NULL) {\r
//\r
// Use UEFI Shell 2.0 method\r
//\r
- return (mEfiShellProtocol->CreateFile(DirectoryName,\r
+ return (gEfiShellProtocol->CreateFile(DirectoryName,\r
EFI_FILE_DIRECTORY,\r
FileHandle\r
- ));\r
+ ));\r
} else {\r
return (ShellOpenFileByName(DirectoryName,\r
FileHandle,\r
EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,\r
EFI_FILE_DIRECTORY\r
- ));\r
+ ));\r
}\r
}\r
\r
the number of bytes written.\r
@param Buffer the buffer to put read data into.\r
\r
- @retval EFI_SUCCESS Data was read.\r
- @retval EFI_NO_MEDIA The device has no media.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required\r
+ @retval EFI_SUCCESS Data was read.\r
+ @retval EFI_NO_MEDIA The device has no media.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required\r
size.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
ShellReadFile(\r
- IN EFI_FILE_HANDLE FileHandle,\r
+ IN SHELL_FILE_HANDLE FileHandle,\r
IN OUT UINTN *BufferSize,\r
OUT VOID *Buffer\r
- ) {\r
+ )\r
+{\r
return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer));\r
}\r
\r
the number of bytes written.\r
@param Buffer the buffer containing data to write is stored.\r
\r
- @retval EFI_SUCCESS Data was written.\r
- @retval EFI_UNSUPPORTED Writes to an open directory are not supported.\r
- @retval EFI_NO_MEDIA The device has no media.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED The device is write-protected.\r
- @retval EFI_ACCESS_DENIED The file was open for read only.\r
- @retval EFI_VOLUME_FULL The volume is full.\r
+ @retval EFI_SUCCESS Data was written.\r
+ @retval EFI_UNSUPPORTED Writes to an open directory are not supported.\r
+ @retval EFI_NO_MEDIA The device has no media.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The device is write-protected.\r
+ @retval EFI_ACCESS_DENIED The file was open for read only.\r
+ @retval EFI_VOLUME_FULL The volume is full.\r
**/\r
EFI_STATUS\r
EFIAPI\r
ShellWriteFile(\r
- IN EFI_FILE_HANDLE FileHandle,\r
+ IN SHELL_FILE_HANDLE FileHandle,\r
IN OUT UINTN *BufferSize,\r
IN VOID *Buffer\r
- ) {\r
+ )\r
+{\r
return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer));\r
}\r
\r
EFI_STATUS\r
EFIAPI\r
ShellCloseFile (\r
- IN EFI_FILE_HANDLE *FileHandle\r
- ) {\r
+ IN SHELL_FILE_HANDLE *FileHandle\r
+ )\r
+{\r
return (FileFunctionMap.CloseFile(*FileHandle));\r
}\r
\r
@retval EFI_SUCCESS the file was closed sucessfully\r
@retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not\r
deleted\r
- @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.\r
**/\r
EFI_STATUS\r
EFIAPI\r
ShellDeleteFile (\r
- IN EFI_FILE_HANDLE *FileHandle\r
- ) {\r
+ IN SHELL_FILE_HANDLE *FileHandle\r
+ )\r
+{\r
return (FileFunctionMap.DeleteFile(*FileHandle));\r
}\r
\r
EFI_STATUS\r
EFIAPI\r
ShellSetFilePosition (\r
- IN EFI_FILE_HANDLE FileHandle,\r
- IN UINT64 Position\r
- ) {\r
+ IN SHELL_FILE_HANDLE FileHandle,\r
+ IN UINT64 Position\r
+ )\r
+{\r
return (FileFunctionMap.SetFilePosition(FileHandle, Position));\r
}\r
\r
EFI_STATUS\r
EFIAPI\r
ShellGetFilePosition (\r
- IN EFI_FILE_HANDLE FileHandle,\r
+ IN SHELL_FILE_HANDLE FileHandle,\r
OUT UINT64 *Position\r
- ) {\r
+ )\r
+{\r
return (FileFunctionMap.GetFilePosition(FileHandle, Position));\r
}\r
/**\r
EFI_STATUS\r
EFIAPI\r
ShellFlushFile (\r
- IN EFI_FILE_HANDLE FileHandle\r
- ) {\r
+ IN SHELL_FILE_HANDLE FileHandle\r
+ )\r
+{\r
return (FileFunctionMap.FlushFile(FileHandle));\r
}\r
\r
-/**\r
- Retrieves the first file from a directory\r
+/** Retrieve first entry from a directory.\r
+\r
+ This function takes an open directory handle and gets information from the\r
+ first entry in the directory. A buffer is allocated to contain\r
+ the information and a pointer to the buffer is returned in *Buffer. The\r
+ caller can use ShellFindNextFile() to get subsequent directory entries.\r
\r
- This function opens a directory and gets the first file's info in the\r
- directory. Caller can use ShellFindNextFile() to get other files. When\r
- complete the caller is responsible for calling FreePool() on Buffer.\r
+ The buffer will be freed by ShellFindNextFile() when the last directory\r
+ entry is read. Otherwise, the caller must free the buffer, using FreePool,\r
+ when finished with it.\r
\r
- @param DirHandle The file handle of the directory to search\r
- @param Buffer Pointer to buffer for file's information\r
+ @param[in] DirHandle The file handle of the directory to search.\r
+ @param[out] Buffer The pointer to the buffer for the file's information.\r
\r
@retval EFI_SUCCESS Found the first file.\r
@retval EFI_NOT_FOUND Cannot find the directory.\r
EFI_STATUS\r
EFIAPI\r
ShellFindFirstFile (\r
- IN EFI_FILE_HANDLE DirHandle,\r
+ IN SHELL_FILE_HANDLE DirHandle,\r
OUT EFI_FILE_INFO **Buffer\r
- ) {\r
+ )\r
+{\r
//\r
// pass to file handle lib\r
//\r
return (FileHandleFindFirstFile(DirHandle, Buffer));\r
}\r
-/**\r
- Retrieves the next file in a directory.\r
+/** Retrieve next entries from a directory.\r
\r
- To use this function, caller must call the LibFindFirstFile() to get the\r
- first file, and then use this function get other files. This function can be\r
- called for several times to get each file's information in the directory. If\r
- the call of ShellFindNextFile() got the last file in the directory, the next\r
- call of this function has no file to get. *NoFile will be set to TRUE and the\r
- Buffer memory will be automatically freed.\r
+ To use this function, the caller must first call the ShellFindFirstFile()\r
+ function to get the first directory entry. Subsequent directory entries are\r
+ retrieved by using the ShellFindNextFile() function. This function can\r
+ be called several times to get each entry from the directory. If the call of\r
+ ShellFindNextFile() retrieved the last directory entry, the next call of\r
+ this function will set *NoFile to TRUE and free the buffer.\r
\r
- @param DirHandle the file handle of the directory\r
- @param Buffer pointer to buffer for file's information\r
- @param NoFile pointer to boolean when last file is found\r
+ @param[in] DirHandle The file handle of the directory.\r
+ @param[out] Buffer The pointer to buffer for file's information.\r
+ @param[out] NoFile The pointer to boolean when last file is found.\r
\r
@retval EFI_SUCCESS Found the next file, or reached last file\r
@retval EFI_NO_MEDIA The device has no media.\r
EFI_STATUS\r
EFIAPI\r
ShellFindNextFile(\r
- IN EFI_FILE_HANDLE DirHandle,\r
+ IN SHELL_FILE_HANDLE DirHandle,\r
OUT EFI_FILE_INFO *Buffer,\r
OUT BOOLEAN *NoFile\r
- ) {\r
+ )\r
+{\r
//\r
// pass to file handle lib\r
//\r
EFI_STATUS\r
EFIAPI\r
ShellGetFileSize (\r
- IN EFI_FILE_HANDLE FileHandle,\r
+ IN SHELL_FILE_HANDLE FileHandle,\r
OUT UINT64 *Size\r
- ) {\r
+ )\r
+{\r
return (FileFunctionMap.GetFileSize(FileHandle, Size));\r
}\r
/**\r
//\r
// Check for UEFI Shell 2.0 protocols\r
//\r
- if (mEfiShellProtocol != NULL) {\r
+ if (gEfiShellProtocol != NULL) {\r
\r
//\r
// We are using UEFI Shell 2.0; see if the event has been triggered\r
//\r
- if (gBS->CheckEvent(mEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) {\r
+ if (gBS->CheckEvent(gEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) {\r
return (FALSE);\r
}\r
return (TRUE);\r
//\r
// using EFI Shell; call the function to check\r
//\r
- ASSERT(mEfiShellEnvironment2 != NULL);\r
- return (mEfiShellEnvironment2->GetExecutionBreak());\r
+ if (mEfiShellEnvironment2 != NULL) {\r
+ return (mEfiShellEnvironment2->GetExecutionBreak());\r
+ }\r
+\r
+ return (FALSE);\r
}\r
/**\r
return the value of an environment variable\r
//\r
// Check for UEFI Shell 2.0 protocols\r
//\r
- if (mEfiShellProtocol != NULL) {\r
- return (mEfiShellProtocol->GetEnv(EnvKey));\r
+ if (gEfiShellProtocol != NULL) {\r
+ return (gEfiShellProtocol->GetEnv(EnvKey));\r
}\r
\r
//\r
- // ASSERT that we must have EFI shell\r
+ // Check for EFI shell\r
//\r
- ASSERT(mEfiShellEnvironment2 != NULL);\r
+ if (mEfiShellEnvironment2 != NULL) {\r
+ return (mEfiShellEnvironment2->GetEnv((CHAR16*)EnvKey));\r
+ }\r
\r
- //\r
- // using EFI Shell\r
- //\r
- return (mEfiShellEnvironment2->GetEnv((CHAR16*)EnvKey));\r
+ return NULL;\r
}\r
/**\r
set the value of an environment variable\r
//\r
// Check for UEFI Shell 2.0 protocols\r
//\r
- if (mEfiShellProtocol != NULL) {\r
- return (mEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));\r
+ if (gEfiShellProtocol != NULL) {\r
+ return (gEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));\r
}\r
\r
//\r
//\r
return (EFI_UNSUPPORTED);\r
}\r
+\r
/**\r
- cause the shell to parse and execute a command line.\r
+ Cause the shell to parse and execute a command line.\r
\r
This function creates a nested instance of the shell and executes the specified\r
-command (CommandLine) with the specified environment (Environment). Upon return,\r
-the status code returned by the specified command is placed in StatusCode.\r
-If Environment is NULL, then the current environment is used and all changes made\r
-by the commands executed will be reflected in the current environment. If the\r
-Environment is non-NULL, then the changes made will be discarded.\r
-The CommandLine is executed from the current working directory on the current\r
-device.\r
-\r
-EnvironmentVariables and Status are only supported for UEFI Shell 2.0.\r
-Output is only supported for pre-UEFI Shell 2.0\r
-\r
- @param ImageHandle Parent image that is starting the operation\r
- @param CommandLine pointer to NULL terminated command line.\r
- @param Output true to display debug output. false to hide it.\r
- @param EnvironmentVariables optional pointer to array of environment variables\r
- in the form "x=y". if NULL current set is used.\r
- @param Status the status of the run command line.\r
-\r
- @retval EFI_SUCCESS the operation completed sucessfully. Status\r
- contains the status code returned.\r
- @retval EFI_INVALID_PARAMETER a parameter contains an invalid value\r
- @retval EFI_OUT_OF_RESOURCES out of resources\r
- @retval EFI_UNSUPPORTED the operation is not allowed.\r
+ command (CommandLine) with the specified environment (Environment). Upon return,\r
+ the status code returned by the specified command is placed in StatusCode.\r
+ If Environment is NULL, then the current environment is used and all changes made\r
+ by the commands executed will be reflected in the current environment. If the\r
+ Environment is non-NULL, then the changes made will be discarded.\r
+ The CommandLine is executed from the current working directory on the current\r
+ device.\r
+\r
+ The EnvironmentVariables pararemeter is ignored in a pre-UEFI Shell 2.0\r
+ environment. The values pointed to by the parameters will be unchanged by the\r
+ ShellExecute() function. The Output parameter has no effect in a\r
+ UEFI Shell 2.0 environment.\r
+\r
+ @param[in] ParentHandle The parent image starting the operation.\r
+ @param[in] CommandLine The pointer to a NULL terminated command line.\r
+ @param[in] Output True to display debug output. False to hide it.\r
+ @param[in] EnvironmentVariables Optional pointer to array of environment variables\r
+ in the form "x=y". If NULL, the current set is used.\r
+ @param[out] Status The status of the run command line.\r
+\r
+ @retval EFI_SUCCESS The operation completed sucessfully. Status\r
+ contains the status code returned.\r
+ @retval EFI_INVALID_PARAMETER A parameter contains an invalid value.\r
+ @retval EFI_OUT_OF_RESOURCES Out of resources.\r
+ @retval EFI_UNSUPPORTED The operation is not allowed.\r
**/\r
EFI_STATUS\r
EFIAPI\r
OUT EFI_STATUS *Status OPTIONAL\r
)\r
{\r
+ EFI_STATUS CmdStatus;\r
//\r
// Check for UEFI Shell 2.0 protocols\r
//\r
- if (mEfiShellProtocol != NULL) {\r
+ if (gEfiShellProtocol != NULL) {\r
//\r
// Call UEFI Shell 2.0 version (not using Output parameter)\r
//\r
- return (mEfiShellProtocol->Execute(ParentHandle,\r
+ return (gEfiShellProtocol->Execute(ParentHandle,\r
CommandLine,\r
EnvironmentVariables,\r
Status));\r
}\r
+\r
//\r
- // ASSERT that we must have EFI shell\r
- //\r
- ASSERT(mEfiShellEnvironment2 != NULL);\r
- //\r
- // Call EFI Shell version (not using EnvironmentVariables or Status parameters)\r
- // Due to oddity in the EFI shell we want to dereference the ParentHandle here\r
+ // Check for EFI shell\r
//\r
- return (mEfiShellEnvironment2->Execute(*ParentHandle,\r
- CommandLine,\r
- Output));\r
+ if (mEfiShellEnvironment2 != NULL) {\r
+ //\r
+ // Call EFI Shell version.\r
+ //\r
+ // Due to an unfixable bug in the EdkShell implementation, we must\r
+ // dereference "ParentHandle" here:\r
+ //\r
+ // 1. The EFI shell installs the EFI_SHELL_ENVIRONMENT2 protocol,\r
+ // identified by gEfiShellEnvironment2Guid.\r
+ // 2. The Execute() member function takes "ParentImageHandle" as first\r
+ // parameter, with type (EFI_HANDLE*).\r
+ // 3. In the EdkShell implementation, SEnvExecute() implements the\r
+ // Execute() member function. It passes "ParentImageHandle" correctly to\r
+ // SEnvDoExecute().\r
+ // 4. SEnvDoExecute() takes the (EFI_HANDLE*), and passes it directly --\r
+ // without de-referencing -- to the HandleProtocol() boot service.\r
+ // 5. But HandleProtocol() takes an EFI_HANDLE.\r
+ //\r
+ // Therefore we must\r
+ // - de-reference "ParentHandle" here, to mask the bug in\r
+ // SEnvDoExecute(), and\r
+ // - pass the resultant EFI_HANDLE as an (EFI_HANDLE*).\r
+ //\r
+ CmdStatus = (mEfiShellEnvironment2->Execute((EFI_HANDLE *)*ParentHandle,\r
+ CommandLine,\r
+ Output));\r
+ //\r
+ // No Status output parameter so just use the returned status\r
+ //\r
+ if (Status != NULL) {\r
+ *Status = CmdStatus;\r
+ }\r
+ //\r
+ // If there was an error, we can't tell if it was from the command or from\r
+ // the Execute() function, so we'll just assume the shell ran successfully\r
+ // and the error came from the command.\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return (EFI_UNSUPPORTED);\r
}\r
+\r
/**\r
Retreives the current directory path\r
\r
name. If the DeviceName is not NULL, it returns the current directory name\r
on specified drive.\r
\r
+ Note that the current directory string should exclude the tailing backslash character.\r
+\r
@param DeviceName the name of the drive to get directory on\r
\r
@retval NULL the directory does not exist\r
CONST CHAR16*\r
EFIAPI\r
ShellGetCurrentDir (\r
- IN CHAR16 *DeviceName OPTIONAL\r
+ IN CHAR16 * CONST DeviceName OPTIONAL\r
)\r
{\r
//\r
// Check for UEFI Shell 2.0 protocols\r
//\r
- if (mEfiShellProtocol != NULL) {\r
- return (mEfiShellProtocol->GetCurDir(DeviceName));\r
+ if (gEfiShellProtocol != NULL) {\r
+ return (gEfiShellProtocol->GetCurDir(DeviceName));\r
}\r
+\r
//\r
- // ASSERT that we must have EFI shell\r
+ // Check for EFI shell\r
//\r
- ASSERT(mEfiShellEnvironment2 != NULL);\r
- return (mEfiShellEnvironment2->CurDir(DeviceName));\r
+ if (mEfiShellEnvironment2 != NULL) {\r
+ return (mEfiShellEnvironment2->CurDir(DeviceName));\r
+ }\r
+\r
+ return (NULL);\r
}\r
/**\r
sets (enabled or disabled) the page break mode\r
//\r
// check for UEFI Shell 2.0\r
//\r
- if (mEfiShellProtocol != NULL) {\r
+ if (gEfiShellProtocol != NULL) {\r
//\r
// Enable with UEFI 2.0 Shell\r
//\r
- mEfiShellProtocol->EnablePageBreak();\r
+ gEfiShellProtocol->EnablePageBreak();\r
return;\r
} else {\r
//\r
- // ASSERT that must have EFI Shell\r
- //\r
- ASSERT(mEfiShellEnvironment2 != NULL);\r
+ // Check for EFI shell\r
//\r
- // Enable with EFI Shell\r
- //\r
- mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);\r
- return;\r
+ if (mEfiShellEnvironment2 != NULL) {\r
+ //\r
+ // Enable with EFI Shell\r
+ //\r
+ mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);\r
+ return;\r
+ }\r
}\r
} else {\r
//\r
// check for UEFI Shell 2.0\r
//\r
- if (mEfiShellProtocol != NULL) {\r
+ if (gEfiShellProtocol != NULL) {\r
//\r
// Disable with UEFI 2.0 Shell\r
//\r
- mEfiShellProtocol->DisablePageBreak();\r
+ gEfiShellProtocol->DisablePageBreak();\r
return;\r
} else {\r
//\r
- // ASSERT that must have EFI Shell\r
- //\r
- ASSERT(mEfiShellEnvironment2 != NULL);\r
+ // Check for EFI shell\r
//\r
- // Disable with EFI Shell\r
- //\r
- mEfiShellEnvironment2->DisablePageBreak ();\r
- return;\r
+ if (mEfiShellEnvironment2 != NULL) {\r
+ //\r
+ // Disable with EFI Shell\r
+ //\r
+ mEfiShellEnvironment2->DisablePageBreak ();\r
+ return;\r
+ }\r
}\r
}\r
}\r
EFI_STATUS Status;\r
CHAR16 *FullName;\r
CHAR16 *FileName;\r
- EFI_FILE_HANDLE Handle;\r
+ SHELL_FILE_HANDLE Handle;\r
EFI_FILE_INFO *Info;\r
} EFI_SHELL_FILE_INFO_NO_CONST;\r
\r
the ShellCloseFileMetaArg function.\r
\r
@param[in] FileList the EFI shell list type\r
- @param[in,out] ListHead the list to add to\r
+ @param[in, out] ListHead the list to add to\r
\r
@retval the resultant head of the double linked new format list;\r
**/\r
LIST_ENTRY*\r
-EFIAPI\r
InternalShellConvertFileListType (\r
IN LIST_ENTRY *FileList,\r
IN OUT LIST_ENTRY *ListHead\r
//\r
for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) {\r
OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);\r
+ ASSERT(OldInfo != NULL);\r
+\r
+ //\r
+ // Skip ones that failed to open...\r
+ //\r
+ if (OldInfo->Status != EFI_SUCCESS) {\r
+ continue;\r
+ }\r
\r
//\r
// make sure the old list was valid\r
//\r
- ASSERT(OldInfo != NULL);\r
ASSERT(OldInfo->Info != NULL);\r
ASSERT(OldInfo->FullName != NULL);\r
ASSERT(OldInfo->FileName != NULL);\r
// allocate a new EFI_SHELL_FILE_INFO object\r
//\r
NewInfo = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
+ if (NewInfo == NULL) {\r
+ ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));\r
+ ListHead = NULL;\r
+ break;\r
+ }\r
\r
//\r
// copy the simple items\r
//\r
// allocate new space to copy strings and structure\r
//\r
- NewInfo->FullName = AllocateZeroPool(StrSize(OldInfo->FullName));\r
- NewInfo->FileName = AllocateZeroPool(StrSize(OldInfo->FileName));\r
- NewInfo->Info = AllocateZeroPool((UINTN)OldInfo->Info->Size);\r
+ NewInfo->FullName = AllocateCopyPool(StrSize(OldInfo->FullName), OldInfo->FullName);\r
+ NewInfo->FileName = AllocateCopyPool(StrSize(OldInfo->FileName), OldInfo->FileName);\r
+ NewInfo->Info = AllocateCopyPool((UINTN)OldInfo->Info->Size, OldInfo->Info);\r
\r
//\r
// make sure all the memory allocations were sucessful\r
//\r
- ASSERT(NewInfo->FullName != NULL);\r
- ASSERT(NewInfo->FileName != NULL);\r
- ASSERT(NewInfo->Info != NULL);\r
+ if (NULL == NewInfo->FullName || NewInfo->FileName == NULL || NewInfo->Info == NULL) {\r
+ //\r
+ // Free the partially allocated new node\r
+ //\r
+ SHELL_FREE_NON_NULL(NewInfo->FullName);\r
+ SHELL_FREE_NON_NULL(NewInfo->FileName);\r
+ SHELL_FREE_NON_NULL(NewInfo->Info);\r
+ SHELL_FREE_NON_NULL(NewInfo);\r
\r
- //\r
- // Copt the strings and structure\r
- //\r
- StrCpy(NewInfo->FullName, OldInfo->FullName);\r
- StrCpy(NewInfo->FileName, OldInfo->FileName);\r
- gBS->CopyMem (NewInfo->Info, OldInfo->Info, (UINTN)OldInfo->Info->Size);\r
+ //\r
+ // Free the previously converted stuff\r
+ //\r
+ ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));\r
+ ListHead = NULL;\r
+ break;\r
+ }\r
\r
//\r
// add that to the list\r
Opens a group of files based on a path.\r
\r
This function uses the Arg to open all the matching files. Each matched\r
- file has a SHELL_FILE_ARG structure to record the file information. These\r
- structures are placed on the list ListHead. Users can get the SHELL_FILE_ARG\r
+ file has a SHELL_FILE_INFO structure to record the file information. These\r
+ structures are placed on the list ListHead. Users can get the SHELL_FILE_INFO\r
structures from ListHead to access each file. This function supports wildcards\r
and will process '?' and '*' as such. the list must be freed with a call to\r
ShellCloseFileMetaArg().\r
\r
@retval EFI_SUCCESS the operation was sucessful and the list head\r
contains the list of opened files\r
- #retval EFI_UNSUPPORTED a previous ShellOpenFileMetaArg must be closed first.\r
- *ListHead is set to NULL.\r
@return != EFI_SUCCESS the operation failed\r
\r
@sa InternalShellConvertFileListType\r
{\r
EFI_STATUS Status;\r
LIST_ENTRY mOldStyleFileList;\r
+ CHAR16 *CleanFilePathStr;\r
\r
//\r
// ASSERT that Arg and ListHead are not NULL\r
ASSERT(Arg != NULL);\r
ASSERT(ListHead != NULL);\r
\r
+ CleanFilePathStr = NULL;\r
+\r
+ Status = InternalShellStripQuotes (Arg, &CleanFilePathStr);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
//\r
// Check for UEFI Shell 2.0 protocols\r
//\r
- if (mEfiShellProtocol != NULL) {\r
+ if (gEfiShellProtocol != NULL) {\r
if (*ListHead == NULL) {\r
*ListHead = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
if (*ListHead == NULL) {\r
+ FreePool(CleanFilePathStr);\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
InitializeListHead(&((*ListHead)->Link));\r
}\r
- Status = mEfiShellProtocol->OpenFileList(Arg,\r
+ Status = gEfiShellProtocol->OpenFileList(CleanFilePathStr,\r
OpenMode,\r
ListHead);\r
if (EFI_ERROR(Status)) {\r
- mEfiShellProtocol->RemoveDupInFileList(ListHead);\r
+ gEfiShellProtocol->RemoveDupInFileList(ListHead);\r
} else {\r
- Status = mEfiShellProtocol->RemoveDupInFileList(ListHead);\r
+ Status = gEfiShellProtocol->RemoveDupInFileList(ListHead);\r
+ }\r
+ if (*ListHead != NULL && IsListEmpty(&(*ListHead)->Link)) {\r
+ FreePool(*ListHead);\r
+ FreePool(CleanFilePathStr);\r
+ *ListHead = NULL;\r
+ return (EFI_NOT_FOUND);\r
}\r
+ FreePool(CleanFilePathStr);\r
return (Status);\r
}\r
\r
//\r
- // ASSERT that we must have EFI shell\r
+ // Check for EFI shell\r
//\r
- ASSERT(mEfiShellEnvironment2 != NULL);\r
-\r
- //\r
- // make sure the list head is initialized\r
- //\r
- InitializeListHead(&mOldStyleFileList);\r
+ if (mEfiShellEnvironment2 != NULL) {\r
+ //\r
+ // make sure the list head is initialized\r
+ //\r
+ InitializeListHead(&mOldStyleFileList);\r
\r
- //\r
- // Get the EFI Shell list of files\r
- //\r
- Status = mEfiShellEnvironment2->FileMetaArg(Arg, &mOldStyleFileList);\r
- if (EFI_ERROR(Status)) {\r
- *ListHead = NULL;\r
- return (Status);\r
- }\r
+ //\r
+ // Get the EFI Shell list of files\r
+ //\r
+ Status = mEfiShellEnvironment2->FileMetaArg(CleanFilePathStr, &mOldStyleFileList);\r
+ if (EFI_ERROR(Status)) {\r
+ *ListHead = NULL;\r
+ FreePool(CleanFilePathStr);\r
+ return (Status);\r
+ }\r
\r
- if (*ListHead == NULL) {\r
- *ListHead = (EFI_SHELL_FILE_INFO *)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
if (*ListHead == NULL) {\r
- return (EFI_OUT_OF_RESOURCES);\r
+ *ListHead = (EFI_SHELL_FILE_INFO *)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));\r
+ if (*ListHead == NULL) {\r
+ FreePool(CleanFilePathStr);\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ InitializeListHead(&((*ListHead)->Link));\r
}\r
- }\r
\r
- //\r
- // Convert that to equivalent of UEFI Shell 2.0 structure\r
- //\r
- InternalShellConvertFileListType(&mOldStyleFileList, &(*ListHead)->Link);\r
+ //\r
+ // Convert that to equivalent of UEFI Shell 2.0 structure\r
+ //\r
+ InternalShellConvertFileListType(&mOldStyleFileList, &(*ListHead)->Link);\r
\r
- //\r
- // Free the EFI Shell version that was converted.\r
- //\r
- mEfiShellEnvironment2->FreeFileList(&mOldStyleFileList);\r
+ //\r
+ // Free the EFI Shell version that was converted.\r
+ //\r
+ mEfiShellEnvironment2->FreeFileList(&mOldStyleFileList);\r
\r
- return (Status);\r
+ if ((*ListHead)->Link.ForwardLink == (*ListHead)->Link.BackLink && (*ListHead)->Link.BackLink == &((*ListHead)->Link)) {\r
+ FreePool(*ListHead);\r
+ *ListHead = NULL;\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ FreePool(CleanFilePathStr);\r
+ return (Status);\r
+ }\r
+\r
+ FreePool(CleanFilePathStr);\r
+ return (EFI_UNSUPPORTED);\r
}\r
/**\r
- Free the linked list returned from ShellOpenFileMetaArg\r
+ Free the linked list returned from ShellOpenFileMetaArg.\r
\r
- if ListHead is NULL then ASSERT()\r
+ if ListHead is NULL then ASSERT().\r
\r
- @param ListHead the pointer to free\r
+ @param ListHead the pointer to free.\r
\r
- @retval EFI_SUCCESS the operation was sucessful\r
+ @retval EFI_SUCCESS the operation was sucessful.\r
**/\r
EFI_STATUS\r
EFIAPI\r
//\r
// Check for UEFI Shell 2.0 protocols\r
//\r
- if (mEfiShellProtocol != NULL) {\r
- return (mEfiShellProtocol->FreeFileList(ListHead));\r
- } else {\r
+ if (gEfiShellProtocol != NULL) {\r
+ return (gEfiShellProtocol->FreeFileList(ListHead));\r
+ } else if (mEfiShellEnvironment2 != NULL) {\r
//\r
// Since this is EFI Shell version we need to free our internally made copy\r
// of the list\r
//\r
for ( Node = GetFirstNode(&(*ListHead)->Link)\r
- ; IsListEmpty(&(*ListHead)->Link) == FALSE\r
+ ; *ListHead != NULL && !IsListEmpty(&(*ListHead)->Link)\r
; Node = GetFirstNode(&(*ListHead)->Link)) {\r
RemoveEntryList(Node);\r
- ((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);\r
+ ((EFI_FILE_PROTOCOL*)((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle)->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);\r
FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName);\r
FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName);\r
FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info);\r
FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node);\r
}\r
+ SHELL_FREE_NON_NULL(*ListHead);\r
return EFI_SUCCESS;\r
}\r
+\r
+ return (EFI_UNSUPPORTED);\r
}\r
\r
/**\r
)\r
{\r
CONST CHAR16 *Path;\r
- EFI_FILE_HANDLE Handle;\r
+ SHELL_FILE_HANDLE Handle;\r
EFI_STATUS Status;\r
CHAR16 *RetVal;\r
CHAR16 *TestPath;\r
\r
RetVal = NULL;\r
\r
+ //\r
+ // First make sure its not an absolute path.\r
+ //\r
+ Status = ShellOpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ, 0);\r
+ if (!EFI_ERROR(Status)){\r
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
+ ASSERT(RetVal == NULL);\r
+ RetVal = StrnCatGrow(&RetVal, NULL, FileName, 0);\r
+ ShellCloseFile(&Handle);\r
+ return (RetVal);\r
+ } else {\r
+ ShellCloseFile(&Handle);\r
+ }\r
+ }\r
+\r
Path = ShellGetEnvironmentVariable(L"cwd");\r
if (Path != NULL) {\r
- Size = StrSize(Path);\r
+ Size = StrSize(Path) + sizeof(CHAR16);\r
Size += StrSize(FileName);\r
TestPath = AllocateZeroPool(Size);\r
- StrCpy(TestPath, Path);\r
- StrCat(TestPath, FileName);\r
+ if (TestPath == NULL) {\r
+ return (NULL);\r
+ }\r
+ StrCpyS(TestPath, Size/sizeof(CHAR16), Path);\r
+ StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");\r
+ StrCatS(TestPath, Size/sizeof(CHAR16), FileName);\r
Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
if (!EFI_ERROR(Status)){\r
- RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
- ShellCloseFile(&Handle);\r
- FreePool(TestPath);\r
- return (RetVal);\r
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
+ ASSERT(RetVal == NULL);\r
+ RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
+ ShellCloseFile(&Handle);\r
+ FreePool(TestPath);\r
+ return (RetVal);\r
+ } else {\r
+ ShellCloseFile(&Handle);\r
+ }\r
}\r
FreePool(TestPath);\r
}\r
Path = ShellGetEnvironmentVariable(L"path");\r
if (Path != NULL) {\r
- Size = StrSize(Path);\r
+ Size = StrSize(Path)+sizeof(CHAR16);\r
Size += StrSize(FileName);\r
TestPath = AllocateZeroPool(Size);\r
+ if (TestPath == NULL) {\r
+ return (NULL);\r
+ }\r
Walker = (CHAR16*)Path;\r
do {\r
CopyMem(TestPath, Walker, StrSize(Walker));\r
- TempChar = StrStr(TestPath, L";");\r
- if (TempChar != NULL) {\r
- *TempChar = CHAR_NULL;\r
- }\r
- StrCat(TestPath, FileName);\r
- if (StrStr(Walker, L";") != NULL) {\r
- Walker = StrStr(Walker, L";") + 1;\r
- } else {\r
- Walker = NULL;\r
- }\r
- Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
- if (!EFI_ERROR(Status)){\r
- RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
- ShellCloseFile(&Handle);\r
- break;\r
+ if (TestPath != NULL) {\r
+ TempChar = StrStr(TestPath, L";");\r
+ if (TempChar != NULL) {\r
+ *TempChar = CHAR_NULL;\r
+ }\r
+ if (TestPath[StrLen(TestPath)-1] != L'\\') {\r
+ StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");\r
+ }\r
+ if (FileName[0] == L'\\') {\r
+ FileName++;\r
+ }\r
+ StrCatS(TestPath, Size/sizeof(CHAR16), FileName);\r
+ if (StrStr(Walker, L";") != NULL) {\r
+ Walker = StrStr(Walker, L";") + 1;\r
+ } else {\r
+ Walker = NULL;\r
+ }\r
+ Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);\r
+ if (!EFI_ERROR(Status)){\r
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {\r
+ ASSERT(RetVal == NULL);\r
+ RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);\r
+ ShellCloseFile(&Handle);\r
+ break;\r
+ } else {\r
+ ShellCloseFile(&Handle);\r
+ }\r
+ }\r
}\r
} while (Walker != NULL && Walker[0] != CHAR_NULL);\r
FreePool(TestPath);\r
CONST CHAR16 *ExtensionWalker;\r
UINTN Size;\r
CHAR16 *TempChar;\r
+ CHAR16 *TempChar2;\r
\r
ASSERT(FileName != NULL);\r
if (FileExtension == NULL) {\r
Size = StrSize(FileName);\r
Size += StrSize(FileExtension);\r
TestPath = AllocateZeroPool(Size);\r
- for (ExtensionWalker = FileExtension ; ; ExtensionWalker = StrStr(ExtensionWalker, L";") + 1 ){\r
- StrCpy(TestPath, FileName);\r
+ if (TestPath == NULL) {\r
+ return (NULL);\r
+ }\r
+ for (ExtensionWalker = FileExtension, TempChar2 = (CHAR16*)FileExtension; TempChar2 != NULL ; ExtensionWalker = TempChar2 + 1){\r
+ StrCpyS(TestPath, Size/sizeof(CHAR16), FileName);\r
if (ExtensionWalker != NULL) {\r
- StrCat(TestPath, ExtensionWalker);\r
+ StrCatS(TestPath, Size/sizeof(CHAR16), ExtensionWalker);\r
}\r
TempChar = StrStr(TestPath, L";");\r
if (TempChar != NULL) {\r
if (RetVal != NULL) {\r
break;\r
}\r
- //\r
- // Must be after first loop...\r
- //\r
- if (StrStr(ExtensionWalker, L";") == NULL) {\r
- break;\r
- }\r
+ ASSERT(ExtensionWalker != NULL);\r
+ TempChar2 = StrStr(ExtensionWalker, L";");\r
}\r
FreePool(TestPath);\r
return (RetVal);\r
typedef struct {\r
LIST_ENTRY Link;\r
CHAR16 *Name;\r
- ParamType Type;\r
+ SHELL_PARAM_TYPE Type;\r
CHAR16 *Value;\r
UINTN OriginalPosition;\r
} SHELL_PARAM_PACKAGE;\r
if Name is NULL then ASSERT();\r
if Type is NULL then ASSERT();\r
\r
- @param Type pointer to type of parameter if it was found\r
@param Name pointer to Name of parameter found\r
@param CheckList List to check against\r
+ @param Type pointer to type of parameter if it was found\r
\r
@retval TRUE the Parameter was found. Type is valid.\r
@retval FALSE the Parameter was not found. Type is not valid.\r
**/\r
BOOLEAN\r
-EFIAPI\r
InternalIsOnCheckList (\r
IN CONST CHAR16 *Name,\r
IN CONST SHELL_PARAM_ITEM *CheckList,\r
- OUT ParamType *Type\r
- ) {\r
+ OUT SHELL_PARAM_TYPE *Type\r
+ )\r
+{\r
SHELL_PARAM_ITEM *TempListItem;\r
+ CHAR16 *TempString;\r
\r
//\r
// ASSERT that all 3 pointer parameters aren't NULL\r
//\r
if ((StrCmp(Name, L"-?") == 0) ||\r
(StrCmp(Name, L"-b") == 0)\r
- ) {\r
+ ) {\r
+ *Type = TypeFlag;\r
return (TRUE);\r
}\r
\r
// If the Type is TypeStart only check the first characters of the passed in param\r
// If it matches set the type and return TRUE\r
//\r
- if (TempListItem->Type == TypeStart && StrnCmp(Name, TempListItem->Name, StrLen(TempListItem->Name)) == 0) {\r
- *Type = TempListItem->Type;\r
- return (TRUE);\r
- } else if (StrCmp(Name, TempListItem->Name) == 0) {\r
+ if (TempListItem->Type == TypeStart) {\r
+ if (StrnCmp(Name, TempListItem->Name, StrLen(TempListItem->Name)) == 0) {\r
+ *Type = TempListItem->Type;\r
+ return (TRUE);\r
+ }\r
+ TempString = NULL;\r
+ TempString = StrnCatGrow(&TempString, NULL, Name, StrLen(TempListItem->Name));\r
+ if (TempString != NULL) {\r
+ if (StringNoCaseCompare(&TempString, &TempListItem->Name) == 0) {\r
+ *Type = TempListItem->Type;\r
+ FreePool(TempString);\r
+ return (TRUE);\r
+ }\r
+ FreePool(TempString);\r
+ }\r
+ } else if (StringNoCaseCompare(&Name, &TempListItem->Name) == 0) {\r
*Type = TempListItem->Type;\r
return (TRUE);\r
}\r
/**\r
Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+'\r
\r
- @param Name pointer to Name of parameter found\r
+ @param[in] Name pointer to Name of parameter found\r
+ @param[in] AlwaysAllowNumbers TRUE to allow numbers, FALSE to not.\r
+ @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise.\r
\r
@retval TRUE the Parameter is a flag.\r
- @retval FALSE the Parameter not a flag\r
+ @retval FALSE the Parameter not a flag.\r
**/\r
BOOLEAN\r
-EFIAPI\r
InternalIsFlag (\r
IN CONST CHAR16 *Name,\r
- IN BOOLEAN AlwaysAllowNumbers\r
+ IN CONST BOOLEAN AlwaysAllowNumbers,\r
+ IN CONST BOOLEAN TimeNumbers\r
)\r
{\r
//\r
//\r
// If we accept numbers then dont return TRUE. (they will be values)\r
//\r
- if (((Name[0] == L'-' || Name[0] == L'+') && ShellIsHexaDecimalDigitCharacter(Name[1])) && AlwaysAllowNumbers != FALSE) {\r
+ if (((Name[0] == L'-' || Name[0] == L'+') && InternalShellIsHexOrDecimalNumber(Name+1, FALSE, FALSE, TimeNumbers)) && AlwaysAllowNumbers) {\r
return (FALSE);\r
}\r
\r
//\r
- // If the Name has a / or - as the first character return TRUE\r
+ // If the Name has a /, +, or - as the first character return TRUE\r
//\r
if ((Name[0] == L'/') ||\r
(Name[0] == L'-') ||\r
(Name[0] == L'+')\r
- ) {\r
+ ) {\r
return (TRUE);\r
}\r
return (FALSE);\r
\r
If no initialization is required, then return RETURN_SUCCESS.\r
\r
- @param CheckList pointer to list of parameters to check\r
- @param CheckPackage pointer to pointer to list checked values\r
- @param ProblemParam optional pointer to pointer to unicode string for\r
+ @param[in] CheckList pointer to list of parameters to check\r
+ @param[out] CheckPackage pointer to pointer to list checked values\r
+ @param[out] ProblemParam optional pointer to pointer to unicode string for\r
the paramater that caused failure. If used then the\r
caller is responsible for freeing the memory.\r
- @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter\r
- @param Argc Count of parameters in Argv\r
- @param Argv pointer to array of parameters\r
+ @param[in] AutoPageBreak will automatically set PageBreakEnabled for "b" parameter\r
+ @param[in] Argv pointer to array of parameters\r
+ @param[in] Argc Count of parameters in Argv\r
+ @param[in] AlwaysAllowNumbers TRUE to allow numbers always, FALSE otherwise.\r
\r
@retval EFI_SUCCESS The operation completed sucessfully.\r
@retval EFI_OUT_OF_RESOURCES A memory allocation failed\r
the invalid command line argument was returned in\r
ProblemParam if provided.\r
**/\r
-STATIC\r
EFI_STATUS\r
-EFIAPI\r
InternalCommandLineParse (\r
IN CONST SHELL_PARAM_ITEM *CheckList,\r
OUT LIST_ENTRY **CheckPackage,\r
IN CONST CHAR16 **Argv,\r
IN UINTN Argc,\r
IN BOOLEAN AlwaysAllowNumbers\r
- ) {\r
+ )\r
+{\r
UINTN LoopCounter;\r
- ParamType CurrentItemType;\r
+ SHELL_PARAM_TYPE CurrentItemType;\r
SHELL_PARAM_PACKAGE *CurrentItemPackage;\r
UINTN GetItemValue;\r
UINTN ValueSize;\r
+ UINTN Count;\r
+ CONST CHAR16 *TempPointer;\r
+ UINTN CurrentValueSize;\r
+ CHAR16 *NewValue;\r
\r
CurrentItemPackage = NULL;\r
- mTotalParameterCount = 0;\r
GetItemValue = 0;\r
ValueSize = 0;\r
+ Count = 0;\r
\r
//\r
// If there is only 1 item we dont need to do anything\r
//\r
- if (Argc <= 1) {\r
+ if (Argc < 1) {\r
*CheckPackage = NULL;\r
return (EFI_SUCCESS);\r
}\r
// initialize the linked list\r
//\r
*CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY));\r
+ if (*CheckPackage == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+\r
InitializeListHead(*CheckPackage);\r
\r
//\r
//\r
// do nothing for NULL argv\r
//\r
- } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) != FALSE) {\r
+ } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType)) {\r
//\r
// We might have leftover if last parameter didnt have optional value\r
//\r
//\r
// this is a flag\r
//\r
- CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
- ASSERT(CurrentItemPackage != NULL);\r
- CurrentItemPackage->Name = AllocatePool(StrSize(Argv[LoopCounter]));\r
- ASSERT(CurrentItemPackage->Name != NULL);\r
- StrCpy(CurrentItemPackage->Name, Argv[LoopCounter]);\r
+ CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));\r
+ if (CurrentItemPackage == NULL) {\r
+ ShellCommandLineFreeVarList(*CheckPackage);\r
+ *CheckPackage = NULL;\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ CurrentItemPackage->Name = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]);\r
+ if (CurrentItemPackage->Name == NULL) {\r
+ ShellCommandLineFreeVarList(*CheckPackage);\r
+ *CheckPackage = NULL;\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
CurrentItemPackage->Type = CurrentItemType;\r
CurrentItemPackage->OriginalPosition = (UINTN)(-1);\r
CurrentItemPackage->Value = NULL;\r
// possibly trigger the next loop(s) to populate the value of this item\r
//\r
case TypeValue:\r
+ case TypeTimeValue:\r
GetItemValue = 1;\r
ValueSize = 0;\r
break;\r
ASSERT(GetItemValue == 0);\r
break;\r
}\r
- } else if (GetItemValue != 0 && InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) == FALSE) {\r
- ASSERT(CurrentItemPackage != NULL);\r
+ } else if (GetItemValue != 0 && CurrentItemPackage != NULL && !InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, (BOOLEAN)(CurrentItemPackage->Type == TypeTimeValue))) {\r
//\r
// get the item VALUE for a previous flag\r
//\r
- CurrentItemPackage->Value = ReallocatePool(ValueSize, ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16), CurrentItemPackage->Value);\r
- ASSERT(CurrentItemPackage->Value != NULL);\r
+ CurrentValueSize = ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
+ NewValue = ReallocatePool(ValueSize, CurrentValueSize, CurrentItemPackage->Value);\r
+ if (NewValue == NULL) {\r
+ SHELL_FREE_NON_NULL (CurrentItemPackage->Value);\r
+ SHELL_FREE_NON_NULL (CurrentItemPackage);\r
+ ShellCommandLineFreeVarList (*CheckPackage);\r
+ *CheckPackage = NULL;\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CurrentItemPackage->Value = NewValue;\r
if (ValueSize == 0) {\r
- StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
+ StrCpyS( CurrentItemPackage->Value,\r
+ CurrentValueSize/sizeof(CHAR16),\r
+ Argv[LoopCounter]\r
+ );\r
} else {\r
- StrCat(CurrentItemPackage->Value, L" ");\r
- StrCat(CurrentItemPackage->Value, Argv[LoopCounter]);\r
+ StrCatS( CurrentItemPackage->Value,\r
+ CurrentValueSize/sizeof(CHAR16),\r
+ L" "\r
+ );\r
+ StrCatS( CurrentItemPackage->Value,\r
+ CurrentValueSize/sizeof(CHAR16),\r
+ Argv[LoopCounter]\r
+ );\r
}\r
ValueSize += StrSize(Argv[LoopCounter]) + sizeof(CHAR16);\r
+\r
GetItemValue--;\r
if (GetItemValue == 0) {\r
InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
}\r
- } else if (InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) == FALSE) {\r
+ } else if (!InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, FALSE)){\r
//\r
// add this one as a non-flag\r
//\r
- CurrentItemPackage = AllocatePool(sizeof(SHELL_PARAM_PACKAGE));\r
- ASSERT(CurrentItemPackage != NULL);\r
+\r
+ TempPointer = Argv[LoopCounter];\r
+ if ((*TempPointer == L'^' && *(TempPointer+1) == L'-')\r
+ || (*TempPointer == L'^' && *(TempPointer+1) == L'/')\r
+ || (*TempPointer == L'^' && *(TempPointer+1) == L'+')\r
+ ){\r
+ TempPointer++;\r
+ }\r
+ CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));\r
+ if (CurrentItemPackage == NULL) {\r
+ ShellCommandLineFreeVarList(*CheckPackage);\r
+ *CheckPackage = NULL;\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
CurrentItemPackage->Name = NULL;\r
CurrentItemPackage->Type = TypePosition;\r
- CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));\r
- ASSERT(CurrentItemPackage->Value != NULL);\r
- StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
- CurrentItemPackage->OriginalPosition = mTotalParameterCount++;\r
+ CurrentItemPackage->Value = AllocateCopyPool(StrSize(TempPointer), TempPointer);\r
+ if (CurrentItemPackage->Value == NULL) {\r
+ ShellCommandLineFreeVarList(*CheckPackage);\r
+ *CheckPackage = NULL;\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ CurrentItemPackage->OriginalPosition = Count++;\r
InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
- } else if (ProblemParam) {\r
+ } else {\r
//\r
// this was a non-recognised flag... error!\r
//\r
- *ProblemParam = AllocatePool(StrSize(Argv[LoopCounter]));\r
- ASSERT(*ProblemParam != NULL);\r
- StrCpy(*ProblemParam, Argv[LoopCounter]);\r
- ShellCommandLineFreeVarList(*CheckPackage);\r
- *CheckPackage = NULL;\r
- return (EFI_VOLUME_CORRUPTED);\r
- } else {\r
+ if (ProblemParam != NULL) {\r
+ *ProblemParam = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]);\r
+ }\r
ShellCommandLineFreeVarList(*CheckPackage);\r
*CheckPackage = NULL;\r
return (EFI_VOLUME_CORRUPTED);\r
\r
If no initialization is required, then return RETURN_SUCCESS.\r
\r
- @param CheckList pointer to list of parameters to check\r
- @param CheckPackage pointer to pointer to list checked values\r
- @param ProblemParam optional pointer to pointer to unicode string for\r
+ @param[in] CheckList The pointer to list of parameters to check.\r
+ @param[out] CheckPackage The package of checked values.\r
+ @param[out] ProblemParam Optional pointer to pointer to unicode string for\r
the paramater that caused failure.\r
- @param AutoPageBreak will automatically set PageBreakEnabled for "b" parameter\r
+ @param[in] AutoPageBreak Will automatically set PageBreakEnabled.\r
+ @param[in] AlwaysAllowNumbers Will never fail for number based flags.\r
\r
@retval EFI_SUCCESS The operation completed sucessfully.\r
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed\r
- @retval EFI_INVALID_PARAMETER A parameter was invalid\r
- @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was\r
- duplicated. the duplicated command line argument\r
- was returned in ProblemParam if provided.\r
- @retval EFI_DEVICE_ERROR the commands contained 2 opposing arguments. one\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.\r
+ @retval EFI_VOLUME_CORRUPTED The command line was corrupt.\r
+ @retval EFI_DEVICE_ERROR The commands contained 2 opposing arguments. One\r
of the command line arguments was returned in\r
ProblemParam if provided.\r
- @retval EFI_NOT_FOUND a argument required a value that was missing.\r
- the invalid command line argument was returned in\r
+ @retval EFI_NOT_FOUND A argument required a value that was missing.\r
+ The invalid command line argument was returned in\r
ProblemParam if provided.\r
**/\r
EFI_STATUS\r
OUT CHAR16 **ProblemParam OPTIONAL,\r
IN BOOLEAN AutoPageBreak,\r
IN BOOLEAN AlwaysAllowNumbers\r
- ) {\r
+ )\r
+{\r
//\r
// ASSERT that CheckList and CheckPackage aren't NULL\r
//\r
//\r
// Check for UEFI Shell 2.0 protocols\r
//\r
- if (mEfiShellParametersProtocol != NULL) {\r
+ if (gEfiShellParametersProtocol != NULL) {\r
return (InternalCommandLineParse(CheckList,\r
CheckPackage,\r
ProblemParam,\r
AutoPageBreak,\r
- (CONST CHAR16**) mEfiShellParametersProtocol->Argv,\r
- mEfiShellParametersProtocol->Argc,\r
+ (CONST CHAR16**) gEfiShellParametersProtocol->Argv,\r
+ gEfiShellParametersProtocol->Argc,\r
AlwaysAllowNumbers));\r
}\r
\r
EFIAPI\r
ShellCommandLineFreeVarList (\r
IN LIST_ENTRY *CheckPackage\r
- ) {\r
+ )\r
+{\r
LIST_ENTRY *Node;\r
\r
//\r
// for each node in the list\r
//\r
for ( Node = GetFirstNode(CheckPackage)\r
- ; IsListEmpty(CheckPackage) == FALSE\r
+ ; !IsListEmpty(CheckPackage)\r
; Node = GetFirstNode(CheckPackage)\r
- ){\r
+ ){\r
//\r
// Remove it from the list\r
//\r
BOOLEAN\r
EFIAPI\r
ShellCommandLineGetFlag (\r
- IN CONST LIST_ENTRY *CheckPackage,\r
- IN CHAR16 *KeyString\r
- ) {\r
+ IN CONST LIST_ENTRY * CONST CheckPackage,\r
+ IN CONST CHAR16 * CONST KeyString\r
+ )\r
+{\r
LIST_ENTRY *Node;\r
+ CHAR16 *TempString;\r
\r
//\r
- // ASSERT that both CheckPackage and KeyString aren't NULL\r
+ // return FALSE for no package or KeyString is NULL\r
//\r
- ASSERT(KeyString != NULL);\r
-\r
- //\r
- // return FALSE for no package\r
- //\r
- if (CheckPackage == NULL) {\r
+ if (CheckPackage == NULL || KeyString == NULL) {\r
return (FALSE);\r
}\r
\r
//\r
// If Type is TypeStart then only compare the begining of the strings\r
//\r
- if ( ((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart\r
- && StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0\r
- ){\r
- return (TRUE);\r
- } else if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
+ if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {\r
+ if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {\r
+ return (TRUE);\r
+ }\r
+ TempString = NULL;\r
+ TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));\r
+ if (TempString != NULL) {\r
+ if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
+ FreePool(TempString);\r
+ return (TRUE);\r
+ }\r
+ FreePool(TempString);\r
+ }\r
+ } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
return (TRUE);\r
}\r
}\r
return (FALSE);\r
}\r
/**\r
- returns value from command line argument\r
+ Returns value from command line argument.\r
\r
- value parameters are in the form of "-<Key> value" or "/<Key> value"\r
+ Value parameters are in the form of "-<Key> value" or "/<Key> value".\r
\r
- if CheckPackage is NULL, then return NULL;\r
+ If CheckPackage is NULL, then return NULL.\r
\r
- @param CheckPackage The package of parsed command line arguments\r
- @param KeyString the Key of the command line argument to check for\r
+ @param[in] CheckPackage The package of parsed command line arguments.\r
+ @param[in] KeyString The Key of the command line argument to check for.\r
\r
- @retval NULL the flag is not on the command line\r
- @return !=NULL pointer to unicode string of the value\r
- **/\r
+ @retval NULL The flag is not on the command line.\r
+ @retval !=NULL The pointer to unicode string of the value.\r
+**/\r
CONST CHAR16*\r
EFIAPI\r
ShellCommandLineGetValue (\r
IN CONST LIST_ENTRY *CheckPackage,\r
IN CHAR16 *KeyString\r
- ) {\r
+ )\r
+{\r
LIST_ENTRY *Node;\r
+ CHAR16 *TempString;\r
\r
//\r
- // check for CheckPackage == NULL\r
+ // return NULL for no package or KeyString is NULL\r
//\r
- if (CheckPackage == NULL) {\r
+ if (CheckPackage == NULL || KeyString == NULL) {\r
return (NULL);\r
}\r
\r
; Node = GetNextNode(CheckPackage, Node)\r
){\r
//\r
- // If the Name matches, return the value (name can be NULL)\r
+ // If the Name matches, return TRUE (and there may be NULL name)\r
//\r
if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
//\r
// If Type is TypeStart then only compare the begining of the strings\r
//\r
- if ( ((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart\r
- && StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0\r
- ){\r
- //\r
- // return the string part after the flag\r
- //\r
- return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));\r
- } else if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
- //\r
- // return the value\r
- //\r
+ if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {\r
+ if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {\r
+ return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));\r
+ }\r
+ TempString = NULL;\r
+ TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));\r
+ if (TempString != NULL) {\r
+ if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
+ FreePool(TempString);\r
+ return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));\r
+ }\r
+ FreePool(TempString);\r
+ }\r
+ } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\r
return (((SHELL_PARAM_PACKAGE*)Node)->Value);\r
}\r
}\r
}\r
return (NULL);\r
}\r
+\r
/**\r
- returns raw value from command line argument\r
+ Returns raw value from command line argument.\r
\r
- raw value parameters are in the form of "value" in a specific position in the list\r
+ Raw value parameters are in the form of "value" in a specific position in the list.\r
\r
- if CheckPackage is NULL, then return NULL;\r
+ If CheckPackage is NULL, then return NULL.\r
\r
- @param CheckPackage The package of parsed command line arguments\r
- @param Position the position of the value\r
+ @param[in] CheckPackage The package of parsed command line arguments.\r
+ @param[in] Position The position of the value.\r
\r
- @retval NULL the flag is not on the command line\r
- @return !=NULL pointer to unicode string of the value\r
+ @retval NULL The flag is not on the command line.\r
+ @retval !=NULL The pointer to unicode string of the value.\r
**/\r
CONST CHAR16*\r
EFIAPI\r
ShellCommandLineGetRawValue (\r
- IN CONST LIST_ENTRY *CheckPackage,\r
- IN UINT32 Position\r
- ) {\r
+ IN CONST LIST_ENTRY * CONST CheckPackage,\r
+ IN UINTN Position\r
+ )\r
+{\r
LIST_ENTRY *Node;\r
\r
//\r
for ( Node = GetFirstNode(CheckPackage)\r
; !IsNull (CheckPackage, Node)\r
; Node = GetNextNode(CheckPackage, Node)\r
- ){\r
+ ){\r
//\r
// If the position matches, return the value\r
//\r
\r
this will not include flags.\r
\r
+ @param[in] CheckPackage The package of parsed command line arguments.\r
+\r
@retval (UINTN)-1 No parsing has ocurred\r
@return other The number of value parameters found\r
**/\r
UINTN\r
EFIAPI\r
ShellCommandLineGetCount(\r
- VOID\r
+ IN CONST LIST_ENTRY *CheckPackage\r
)\r
{\r
- return (mTotalParameterCount);\r
+ LIST_ENTRY *Node1;\r
+ UINTN Count;\r
+\r
+ if (CheckPackage == NULL) {\r
+ return (0);\r
+ }\r
+ for ( Node1 = GetFirstNode(CheckPackage), Count = 0\r
+ ; !IsNull (CheckPackage, Node1)\r
+ ; Node1 = GetNextNode(CheckPackage, Node1)\r
+ ){\r
+ if (((SHELL_PARAM_PACKAGE*)Node1)->Name == NULL) {\r
+ Count++;\r
+ }\r
+ }\r
+ return (Count);\r
}\r
\r
/**\r
- Determins if a parameter is duplicated.\r
+ Determines if a parameter is duplicated.\r
\r
If Param is not NULL then it will point to a callee allocated string buffer\r
with the parameter value if a duplicate is found.\r
for ( Node1 = GetFirstNode(CheckPackage)\r
; !IsNull (CheckPackage, Node1)\r
; Node1 = GetNextNode(CheckPackage, Node1)\r
- ){\r
+ ){\r
for ( Node2 = GetNextNode(CheckPackage, Node1)\r
; !IsNull (CheckPackage, Node2)\r
; Node2 = GetNextNode(CheckPackage, Node2)\r
- ){\r
- if (StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) {\r
+ ){\r
+ if ((((SHELL_PARAM_PACKAGE*)Node1)->Name != NULL) && (((SHELL_PARAM_PACKAGE*)Node2)->Name != NULL) && StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) {\r
if (Param != NULL) {\r
*Param = NULL;\r
*Param = StrnCatGrow(Param, NULL, ((SHELL_PARAM_PACKAGE*)Node1)->Name, 0);\r
\r
If the string would grow bigger than NewSize it will halt and return error.\r
\r
- @param[in] SourceString String with source buffer\r
- @param[in,out] NewString String with resultant buffer\r
- @param[in] NewSize Size in bytes of NewString\r
- @param[in] FindTarget String to look for\r
- @param[in[ ReplaceWith String to replace FindTarget with\r
- @param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^'\r
- immediately before it.\r
+ @param[in] SourceString The string with source buffer.\r
+ @param[in, out] NewString The string with resultant buffer.\r
+ @param[in] NewSize The size in bytes of NewString.\r
+ @param[in] FindTarget The string to look for.\r
+ @param[in] ReplaceWith The string to replace FindTarget with.\r
+ @param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^'\r
+ immediately before it.\r
+ @param[in] ParameterReplacing If TRUE will add "" around items with spaces.\r
\r
@retval EFI_INVALID_PARAMETER SourceString was NULL.\r
@retval EFI_INVALID_PARAMETER NewString was NULL.\r
@retval EFI_INVALID_PARAMETER SourceString had length < 1.\r
@retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold\r
the new string (truncation occurred).\r
- @retval EFI_SUCCESS the string was sucessfully copied with replacement.\r
+ @retval EFI_SUCCESS The string was successfully copied with replacement.\r
**/\r
-\r
EFI_STATUS\r
EFIAPI\r
-ShellCopySearchAndReplace2(\r
+ShellCopySearchAndReplace(\r
IN CHAR16 CONST *SourceString,\r
- IN CHAR16 *NewString,\r
+ IN OUT CHAR16 *NewString,\r
IN UINTN NewSize,\r
IN CONST CHAR16 *FindTarget,\r
IN CONST CHAR16 *ReplaceWith,\r
- IN CONST BOOLEAN SkipPreCarrot\r
+ IN CONST BOOLEAN SkipPreCarrot,\r
+ IN CONST BOOLEAN ParameterReplacing\r
)\r
{\r
UINTN Size;\r
+ CHAR16 *Replace;\r
+\r
if ( (SourceString == NULL)\r
|| (NewString == NULL)\r
|| (FindTarget == NULL)\r
|| (ReplaceWith == NULL)\r
|| (StrLen(FindTarget) < 1)\r
|| (StrLen(SourceString) < 1)\r
- ){\r
+ ){\r
return (EFI_INVALID_PARAMETER);\r
}\r
- NewString = SetMem16(NewString, NewSize, CHAR_NULL);\r
+ Replace = NULL;\r
+ if (StrStr(ReplaceWith, L" ") == NULL || !ParameterReplacing) {\r
+ Replace = StrnCatGrow(&Replace, NULL, ReplaceWith, 0);\r
+ } else {\r
+ Replace = AllocateZeroPool(StrSize(ReplaceWith) + 2*sizeof(CHAR16));\r
+ if (Replace != NULL) {\r
+ UnicodeSPrint(Replace, StrSize(ReplaceWith) + 2*sizeof(CHAR16), L"\"%s\"", ReplaceWith);\r
+ }\r
+ }\r
+ if (Replace == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ NewString = ZeroMem(NewString, NewSize);\r
while (*SourceString != CHAR_NULL) {\r
//\r
- // if we find the FindTarget and either Skip == FALSE or Skip == TRUE and we\r
+ // if we find the FindTarget and either Skip == FALSE or Skip and we\r
// dont have a carrot do a replace...\r
//\r
if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0\r
- && ((SkipPreCarrot && *(SourceString-1) != L'^') || SkipPreCarrot == FALSE)\r
- ){\r
+ && ((SkipPreCarrot && *(SourceString-1) != L'^') || !SkipPreCarrot)\r
+ ){\r
SourceString += StrLen(FindTarget);\r
Size = StrSize(NewString);\r
- if ((Size + (StrLen(ReplaceWith)*sizeof(CHAR16))) > NewSize) {\r
+ if ((Size + (StrLen(Replace)*sizeof(CHAR16))) > NewSize) {\r
+ FreePool(Replace);\r
return (EFI_BUFFER_TOO_SMALL);\r
}\r
- StrCat(NewString, ReplaceWith);\r
+ StrCatS(NewString, NewSize/sizeof(CHAR16), Replace);\r
} else {\r
Size = StrSize(NewString);\r
if (Size + sizeof(CHAR16) > NewSize) {\r
+ FreePool(Replace);\r
return (EFI_BUFFER_TOO_SMALL);\r
}\r
- StrnCat(NewString, SourceString, 1);\r
+ StrnCatS(NewString, NewSize/sizeof(CHAR16), SourceString, 1);\r
SourceString++;\r
}\r
}\r
+ FreePool(Replace);\r
return (EFI_SUCCESS);\r
}\r
\r
@retval !EFI_SUCCESS The operation failed.\r
**/\r
EFI_STATUS\r
-EFIAPI\r
InternalPrintTo (\r
IN CONST CHAR16 *String\r
)\r
{\r
UINTN Size;\r
Size = StrSize(String) - sizeof(CHAR16);\r
- if (mEfiShellParametersProtocol != NULL) {\r
- return (mEfiShellParametersProtocol->StdOut->Write(mEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));\r
+ if (Size == 0) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+ if (gEfiShellParametersProtocol != NULL) {\r
+ return (gEfiShellProtocol->WriteFile(gEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));\r
}\r
if (mEfiShellInterface != NULL) {\r
+ if (mEfiShellInterface->RedirArgc == 0) {\r
//\r
// Divide in half for old shell. Must be string length not size.\r
- //\r
- Size /= 2;\r
- return ( mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut, &Size, (VOID*)String));\r
+ //\r
+ Size /=2; // Divide in half only when no redirection.\r
+ }\r
+ return (mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut, &Size, (VOID*)String));\r
}\r
ASSERT(FALSE);\r
return (EFI_UNSUPPORTED);\r
\r
Note: The background color is controlled by the shell command cls.\r
\r
- @param[in] Row the row to print at\r
@param[in] Col the column to print at\r
+ @param[in] Row the row to print at\r
@param[in] Format the format string\r
@param[in] Marker the marker for the variable argument list\r
\r
- @return the number of characters printed to the screen\r
+ @return EFI_SUCCESS The operation was successful.\r
+ @return EFI_DEVICE_ERROR The console device reported an error.\r
**/\r
-\r
-UINTN\r
-EFIAPI\r
+EFI_STATUS\r
InternalShellPrintWorker(\r
IN INT32 Col OPTIONAL,\r
IN INT32 Row OPTIONAL,\r
IN CONST CHAR16 *Format,\r
- VA_LIST Marker\r
+ IN VA_LIST Marker\r
)\r
{\r
- UINTN Return;\r
EFI_STATUS Status;\r
- UINTN NormalAttribute;\r
CHAR16 *ResumeLocation;\r
CHAR16 *FormatWalker;\r
+ UINTN OriginalAttribute;\r
+ CHAR16 *mPostReplaceFormat;\r
+ CHAR16 *mPostReplaceFormat2;\r
+\r
+ mPostReplaceFormat = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
+ mPostReplaceFormat2 = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));\r
+\r
+ if (mPostReplaceFormat == NULL || mPostReplaceFormat2 == NULL) {\r
+ SHELL_FREE_NON_NULL(mPostReplaceFormat);\r
+ SHELL_FREE_NON_NULL(mPostReplaceFormat2);\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ OriginalAttribute = gST->ConOut->Mode->Attribute;\r
\r
//\r
// Back and forth each time fixing up 1 of our flags...\r
//\r
- Status = ShellLibCopySearchAndReplace(Format, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N");\r
+ Status = ShellCopySearchAndReplace(Format, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N", FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
- Status = ShellLibCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E");\r
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E", FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
- Status = ShellLibCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H");\r
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H", FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
- Status = ShellLibCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B");\r
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B", FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
- Status = ShellLibCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V");\r
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V", FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
\r
//\r
// Use the last buffer from replacing to print from...\r
//\r
- Return = UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker);\r
+ UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker);\r
\r
if (Col != -1 && Row != -1) {\r
Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);\r
- ASSERT_EFI_ERROR(Status);\r
}\r
\r
- NormalAttribute = gST->ConOut->Mode->Attribute;\r
FormatWalker = mPostReplaceFormat2;\r
while (*FormatWalker != CHAR_NULL) {\r
//\r
//\r
// print the current FormatWalker string\r
//\r
- Status = InternalPrintTo(FormatWalker);\r
- ASSERT_EFI_ERROR(Status);\r
+ if (StrLen(FormatWalker)>0) {\r
+ Status = InternalPrintTo(FormatWalker);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ }\r
+\r
//\r
// update the attribute\r
//\r
if (ResumeLocation != NULL) {\r
- switch (*(ResumeLocation+1)) {\r
- case (L'N'):\r
- gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
- break;\r
- case (L'E'):\r
- gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
- break;\r
- case (L'H'):\r
- gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
- break;\r
- case (L'B'):\r
- gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
- break;\r
- case (L'V'):\r
- gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((NormalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
- break;\r
- default:\r
- //\r
- // Print a simple '%' symbol\r
- //\r
- Status = InternalPrintTo(L"%");\r
- ASSERT_EFI_ERROR(Status);\r
- ResumeLocation = ResumeLocation - 1;\r
- break;\r
+ if ((ResumeLocation != mPostReplaceFormat2) && (*(ResumeLocation-1) == L'^')) {\r
+ //\r
+ // Move cursor back 1 position to overwrite the ^\r
+ //\r
+ gST->ConOut->SetCursorPosition(gST->ConOut, gST->ConOut->Mode->CursorColumn - 1, gST->ConOut->Mode->CursorRow);\r
+\r
+ //\r
+ // Print a simple '%' symbol\r
+ //\r
+ Status = InternalPrintTo(L"%");\r
+ ResumeLocation = ResumeLocation - 1;\r
+ } else {\r
+ switch (*(ResumeLocation+1)) {\r
+ case (L'N'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);\r
+ break;\r
+ case (L'E'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ case (L'H'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ case (L'B'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTBLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ case (L'V'):\r
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTGREEN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));\r
+ break;\r
+ default:\r
+ //\r
+ // Print a simple '%' symbol\r
+ //\r
+ Status = InternalPrintTo(L"%");\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ResumeLocation = ResumeLocation - 1;\r
+ break;\r
+ }\r
}\r
} else {\r
//\r
// reset to normal now...\r
//\r
- gST->ConOut->SetAttribute(gST->ConOut, NormalAttribute);\r
break;\r
}\r
\r
FormatWalker = ResumeLocation + 2;\r
}\r
\r
- return (Return);\r
+ gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);\r
+\r
+ SHELL_FREE_NON_NULL(mPostReplaceFormat);\r
+ SHELL_FREE_NON_NULL(mPostReplaceFormat2);\r
+ return (Status);\r
}\r
\r
/**\r
\r
Note: The background color is controlled by the shell command cls.\r
\r
- @param[in] Row the row to print at\r
@param[in] Col the column to print at\r
+ @param[in] Row the row to print at\r
@param[in] Format the format string\r
+ @param[in] ... The variable argument list.\r
\r
- @return the number of characters printed to the screen\r
+ @return EFI_SUCCESS The printing was successful.\r
+ @return EFI_DEVICE_ERROR The console device reported an error.\r
**/\r
-\r
-UINTN\r
+EFI_STATUS\r
EFIAPI\r
ShellPrintEx(\r
IN INT32 Col OPTIONAL,\r
)\r
{\r
VA_LIST Marker;\r
- EFI_STATUS Status;\r
+ EFI_STATUS RetVal;\r
+ if (Format == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
VA_START (Marker, Format);\r
- Status = InternalShellPrintWorker(Col, Row, Format, Marker);\r
+ RetVal = InternalShellPrintWorker(Col, Row, Format, Marker);\r
VA_END(Marker);\r
- return(Status);\r
+ return(RetVal);\r
}\r
\r
/**\r
\r
Note: The background color is controlled by the shell command cls.\r
\r
- @param[in] Row The row to print at.\r
@param[in] Col The column to print at.\r
+ @param[in] Row The row to print at.\r
@param[in] Language The language of the string to retrieve. If this parameter\r
is NULL, then the current platform language is used.\r
@param[in] HiiFormatStringId The format string Id for getting from Hii.\r
@param[in] HiiFormatHandle The format string Handle for getting from Hii.\r
+ @param[in] ... The variable argument list.\r
\r
- @return the number of characters printed to the screen.\r
+ @return EFI_SUCCESS The printing was successful.\r
+ @return EFI_DEVICE_ERROR The console device reported an error.\r
**/\r
-UINTN\r
+EFI_STATUS\r
EFIAPI\r
ShellPrintHiiEx(\r
IN INT32 Col OPTIONAL,\r
IN INT32 Row OPTIONAL,\r
IN CONST CHAR8 *Language OPTIONAL,\r
IN CONST EFI_STRING_ID HiiFormatStringId,\r
- IN CONST EFI_HANDLE HiiFormatHandle,\r
+ IN CONST EFI_HII_HANDLE HiiFormatHandle,\r
...\r
)\r
{\r
VA_LIST Marker;\r
CHAR16 *HiiFormatString;\r
- UINTN RetVal;\r
+ EFI_STATUS RetVal;\r
+\r
+ RetVal = EFI_DEVICE_ERROR;\r
\r
VA_START (Marker, HiiFormatHandle);\r
HiiFormatString = HiiGetString(HiiFormatHandle, HiiFormatStringId, Language);\r
- ASSERT(HiiFormatString != NULL);\r
-\r
- RetVal = InternalShellPrintWorker(Col, Row, HiiFormatString, Marker);\r
-\r
- FreePool(HiiFormatString);\r
+ if (HiiFormatString != NULL) {\r
+ RetVal = InternalShellPrintWorker (Col, Row, HiiFormatString, Marker);\r
+ SHELL_FREE_NON_NULL (HiiFormatString);\r
+ }\r
VA_END(Marker);\r
\r
return (RetVal);\r
\r
@param[in] DirName Path to directory to test.\r
\r
- @retval EFI_SUCCESS The Path represents a directory\r
- @retval EFI_NOT_FOUND The Path does not represent a directory\r
- @return other The path failed to open\r
+ @retval EFI_SUCCESS The Path represents a directory\r
+ @retval EFI_NOT_FOUND The Path does not represent a directory\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @return The path failed to open\r
**/\r
EFI_STATUS\r
EFIAPI\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_FILE_HANDLE Handle;\r
+ SHELL_FILE_HANDLE Handle;\r
+ CHAR16 *TempLocation;\r
+ CHAR16 *TempLocation2;\r
\r
ASSERT(DirName != NULL);\r
\r
- Handle = NULL;\r
+ Handle = NULL;\r
+ TempLocation = NULL;\r
\r
Status = ShellOpenFileByName(DirName, &Handle, EFI_FILE_MODE_READ, 0);\r
if (EFI_ERROR(Status)) {\r
+ //\r
+ // try good logic first.\r
+ //\r
+ if (gEfiShellProtocol != NULL) {\r
+ TempLocation = StrnCatGrow(&TempLocation, NULL, DirName, 0);\r
+ if (TempLocation == NULL) {\r
+ ShellCloseFile(&Handle);\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ TempLocation2 = StrStr(TempLocation, L":");\r
+ if (TempLocation2 != NULL && StrLen(StrStr(TempLocation, L":")) == 2) {\r
+ *(TempLocation2+1) = CHAR_NULL;\r
+ }\r
+ if (gEfiShellProtocol->GetDevicePathFromMap(TempLocation) != NULL) {\r
+ FreePool(TempLocation);\r
+ return (EFI_SUCCESS);\r
+ }\r
+ FreePool(TempLocation);\r
+ } else {\r
+ //\r
+ // probably a map name?!?!!?\r
+ //\r
+ TempLocation = StrStr(DirName, L"\\");\r
+ if (TempLocation != NULL && *(TempLocation+1) == CHAR_NULL) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+ }\r
return (Status);\r
}\r
\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_FILE_HANDLE Handle;\r
+ SHELL_FILE_HANDLE Handle;\r
\r
ASSERT(Name != NULL);\r
\r
EFIAPI\r
ShellIsFileInPath(\r
IN CONST CHAR16 *Name\r
- ) {\r
+ )\r
+{\r
CHAR16 *NewName;\r
EFI_STATUS Status;\r
\r
if (!EFI_ERROR(ShellIsFile(Name))) {\r
- return (TRUE);\r
+ return (EFI_SUCCESS);\r
}\r
\r
NewName = ShellFindFilePath(Name);\r
FreePool(NewName);\r
return (Status);\r
}\r
+\r
+/**\r
+ Function return the number converted from a hex representation of a number.\r
+\r
+ Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid\r
+ result. Use ShellConvertStringToUint64 instead.\r
+\r
+ @param[in] String String representation of a number.\r
+\r
+ @return The unsigned integer result of the conversion.\r
+ @retval (UINTN)(-1) An error occurred.\r
+**/\r
+UINTN\r
+EFIAPI\r
+ShellHexStrToUintn(\r
+ IN CONST CHAR16 *String\r
+ )\r
+{\r
+ UINT64 RetVal;\r
+\r
+ if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, TRUE, TRUE))) {\r
+ return ((UINTN)RetVal);\r
+ }\r
+\r
+ return ((UINTN)(-1));\r
+}\r
+\r
/**\r
Function to determine whether a string is decimal or hex representation of a number\r
- and return the number converted from the string.\r
+ and return the number converted from the string. Spaces are always skipped.\r
\r
@param[in] String String representation of a number\r
\r
- @retval all the number\r
+ @return the number\r
+ @retval (UINTN)(-1) An error ocurred.\r
**/\r
UINTN\r
EFIAPI\r
IN CONST CHAR16 *String\r
)\r
{\r
- CONST CHAR16 *Walker;\r
- for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);\r
- if (Walker == NULL || *Walker == CHAR_NULL) {\r
- ASSERT(FALSE);\r
- return ((UINTN)(-1));\r
- } else {\r
- if (StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){\r
- return (StrHexToUintn(Walker));\r
- }\r
- return (StrDecimalToUintn(Walker));\r
+ UINT64 RetVal;\r
+ BOOLEAN Hex;\r
+\r
+ Hex = FALSE;\r
+\r
+ if (!InternalShellIsHexOrDecimalNumber(String, Hex, TRUE, FALSE)) {\r
+ Hex = TRUE;\r
+ }\r
+\r
+ if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, Hex, TRUE))) {\r
+ return ((UINTN)RetVal);\r
}\r
+ return ((UINTN)(-1));\r
}\r
\r
/**\r
if Destination's current length (including NULL terminator) is already more then\r
CurrentSize, then ASSERT()\r
\r
- @param[in,out] Destination The String to append onto\r
- @param[in,out] CurrentSize on call the number of bytes in Destination. On\r
+ @param[in, out] Destination The String to append onto\r
+ @param[in, out] CurrentSize on call the number of bytes in Destination. On\r
return possibly the new size (still in bytes). if NULL\r
then allocate whatever is needed.\r
@param[in] Source The String to append from\r
//\r
if (CurrentSize != NULL) {\r
NewSize = *CurrentSize;\r
- while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {\r
- NewSize += 2 * Count * sizeof(CHAR16);\r
+ if (NewSize < DestinationStartSize + (Count * sizeof(CHAR16))) {\r
+ while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {\r
+ NewSize += 2 * Count * sizeof(CHAR16);\r
+ }\r
+ *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
+ *CurrentSize = NewSize;\r
}\r
- *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);\r
- *CurrentSize = NewSize;\r
} else {\r
- *Destination = AllocateZeroPool((Count+1)*sizeof(CHAR16));\r
+ NewSize = (Count+1)*sizeof(CHAR16);\r
+ *Destination = AllocateZeroPool(NewSize);\r
}\r
\r
//\r
// Now use standard StrnCat on a big enough buffer\r
//\r
- return StrnCat(*Destination, Source, Count);\r
+ if (*Destination == NULL) {\r
+ return (NULL);\r
+ }\r
+\r
+ StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, Count);\r
+ return *Destination;\r
+}\r
+\r
+/**\r
+ Prompt the user and return the resultant answer to the requestor.\r
+\r
+ This function will display the requested question on the shell prompt and then\r
+ wait for an appropriate answer to be input from the console.\r
+\r
+ if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, ShellPromptResponseTypeQuitContinue\r
+ or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE.\r
+\r
+ if the SHELL_PROMPT_REQUEST_TYPE is ShellPromptResponseTypeFreeform then *Response is of type\r
+ CHAR16*.\r
+\r
+ In either case *Response must be callee freed if Response was not NULL;\r
+\r
+ @param Type What type of question is asked. This is used to filter the input\r
+ to prevent invalid answers to question.\r
+ @param Prompt Pointer to string prompt to use to request input.\r
+ @param Response Pointer to Response which will be populated upon return.\r
+\r
+ @retval EFI_SUCCESS The operation was sucessful.\r
+ @retval EFI_UNSUPPORTED The operation is not supported as requested.\r
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.\r
+ @return other The operation failed.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPromptForResponse (\r
+ IN SHELL_PROMPT_REQUEST_TYPE Type,\r
+ IN CHAR16 *Prompt OPTIONAL,\r
+ IN OUT VOID **Response OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_INPUT_KEY Key;\r
+ UINTN EventIndex;\r
+ SHELL_PROMPT_RESPONSE *Resp;\r
+ UINTN Size;\r
+ CHAR16 *Buffer;\r
+\r
+ Status = EFI_UNSUPPORTED;\r
+ Resp = NULL;\r
+ Buffer = NULL;\r
+ Size = 0;\r
+ if (Type != ShellPromptResponseTypeFreeform) {\r
+ Resp = (SHELL_PROMPT_RESPONSE*)AllocateZeroPool(sizeof(SHELL_PROMPT_RESPONSE));\r
+ if (Resp == NULL) {\r
+ if (Response != NULL) {\r
+ *Response = NULL;\r
+ }\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ }\r
+\r
+ switch(Type) {\r
+ case ShellPromptResponseTypeQuitContinue:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ if (Key.UnicodeChar == L'Q' || Key.UnicodeChar ==L'q') {\r
+ *Resp = ShellPromptResponseQuit;\r
+ } else {\r
+ *Resp = ShellPromptResponseContinue;\r
+ }\r
+ break;\r
+ case ShellPromptResponseTypeYesNoCancel:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = ShellPromptResponseMax;\r
+ while (*Resp == ShellPromptResponseMax) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ switch (Key.UnicodeChar) {\r
+ case L'Y':\r
+ case L'y':\r
+ *Resp = ShellPromptResponseYes;\r
+ break;\r
+ case L'N':\r
+ case L'n':\r
+ *Resp = ShellPromptResponseNo;\r
+ break;\r
+ case L'C':\r
+ case L'c':\r
+ *Resp = ShellPromptResponseCancel;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case ShellPromptResponseTypeYesNoAllCancel:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = ShellPromptResponseMax;\r
+ while (*Resp == ShellPromptResponseMax) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+\r
+ if (Key.UnicodeChar <= 127 && Key.UnicodeChar >= 32) {\r
+ ShellPrintEx (-1, -1, L"%c", Key.UnicodeChar);\r
+ }\r
+\r
+ switch (Key.UnicodeChar) {\r
+ case L'Y':\r
+ case L'y':\r
+ *Resp = ShellPromptResponseYes;\r
+ break;\r
+ case L'N':\r
+ case L'n':\r
+ *Resp = ShellPromptResponseNo;\r
+ break;\r
+ case L'A':\r
+ case L'a':\r
+ *Resp = ShellPromptResponseAll;\r
+ break;\r
+ case L'C':\r
+ case L'c':\r
+ *Resp = ShellPromptResponseCancel;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case ShellPromptResponseTypeEnterContinue:\r
+ case ShellPromptResponseTypeAnyKeyContinue:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = ShellPromptResponseMax;\r
+ while (*Resp == ShellPromptResponseMax) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ if (Type == ShellPromptResponseTypeEnterContinue) {\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ *Resp = ShellPromptResponseContinue;\r
+ break;\r
+ }\r
+ }\r
+ if (Type == ShellPromptResponseTypeAnyKeyContinue) {\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ ASSERT_EFI_ERROR(Status);\r
+ *Resp = ShellPromptResponseContinue;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case ShellPromptResponseTypeYesNo:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ //\r
+ // wait for valid response\r
+ //\r
+ *Resp = ShellPromptResponseMax;\r
+ while (*Resp == ShellPromptResponseMax) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ switch (Key.UnicodeChar) {\r
+ case L'Y':\r
+ case L'y':\r
+ *Resp = ShellPromptResponseYes;\r
+ break;\r
+ case L'N':\r
+ case L'n':\r
+ *Resp = ShellPromptResponseNo;\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ case ShellPromptResponseTypeFreeform:\r
+ if (Prompt != NULL) {\r
+ ShellPrintEx(-1, -1, L"%s", Prompt);\r
+ }\r
+ while(1) {\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);\r
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (EFI_ERROR(Status)) {\r
+ break;\r
+ }\r
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ break;\r
+ }\r
+ ASSERT((Buffer == NULL && Size == 0) || (Buffer != NULL));\r
+ StrnCatGrow(&Buffer, &Size, &Key.UnicodeChar, 1);\r
+ }\r
+ break;\r
+ //\r
+ // This is the location to add new prompt types.\r
+ // If your new type loops remember to add ExecutionBreak support.\r
+ //\r
+ default:\r
+ ASSERT(FALSE);\r
+ }\r
+\r
+ if (Response != NULL) {\r
+ if (Resp != NULL) {\r
+ *Response = Resp;\r
+ } else if (Buffer != NULL) {\r
+ *Response = Buffer;\r
+ } else {\r
+ *Response = NULL;\r
+ }\r
+ } else {\r
+ if (Resp != NULL) {\r
+ FreePool(Resp);\r
+ }\r
+ if (Buffer != NULL) {\r
+ FreePool(Buffer);\r
+ }\r
+ }\r
+\r
+ ShellPrintEx(-1, -1, L"\r\n");\r
+ return (Status);\r
+}\r
+\r
+/**\r
+ Prompt the user and return the resultant answer to the requestor.\r
+\r
+ This function is the same as ShellPromptForResponse, except that the prompt is\r
+ automatically pulled from HII.\r
+\r
+ @param Type What type of question is asked. This is used to filter the input\r
+ to prevent invalid answers to question.\r
+ @param[in] HiiFormatStringId The format string Id for getting from Hii.\r
+ @param[in] HiiFormatHandle The format string Handle for getting from Hii.\r
+ @param Response Pointer to Response which will be populated upon return.\r
+\r
+ @retval EFI_SUCCESS the operation was sucessful.\r
+ @return other the operation failed.\r
+\r
+ @sa ShellPromptForResponse\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPromptForResponseHii (\r
+ IN SHELL_PROMPT_REQUEST_TYPE Type,\r
+ IN CONST EFI_STRING_ID HiiFormatStringId,\r
+ IN CONST EFI_HII_HANDLE HiiFormatHandle,\r
+ IN OUT VOID **Response\r
+ )\r
+{\r
+ CHAR16 *Prompt;\r
+ EFI_STATUS Status;\r
+\r
+ Prompt = HiiGetString(HiiFormatHandle, HiiFormatStringId, NULL);\r
+ Status = ShellPromptForResponse(Type, Prompt, Response);\r
+ FreePool(Prompt);\r
+ return (Status);\r
+}\r
+\r
+/**\r
+ Function to determin if an entire string is a valid number.\r
+\r
+ If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.\r
+\r
+ @param[in] String The string to evaluate.\r
+ @param[in] ForceHex TRUE - always assume hex.\r
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.\r
+ @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise.\r
+\r
+ @retval TRUE It is all numeric (dec/hex) characters.\r
+ @retval FALSE There is a non-numeric character.\r
+**/\r
+BOOLEAN\r
+InternalShellIsHexOrDecimalNumber (\r
+ IN CONST CHAR16 *String,\r
+ IN CONST BOOLEAN ForceHex,\r
+ IN CONST BOOLEAN StopAtSpace,\r
+ IN CONST BOOLEAN TimeNumbers\r
+ )\r
+{\r
+ BOOLEAN Hex;\r
+ BOOLEAN LeadingZero;\r
+\r
+ if (String == NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // chop off a single negative sign\r
+ //\r
+ if (*String == L'-') {\r
+ String++;\r
+ }\r
+\r
+ if (*String == CHAR_NULL) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // chop leading zeroes\r
+ //\r
+ LeadingZero = FALSE;\r
+ while(*String == L'0'){\r
+ String++;\r
+ LeadingZero = TRUE;\r
+ }\r
+ //\r
+ // allow '0x' or '0X', but not 'x' or 'X'\r
+ //\r
+ if (*String == L'x' || *String == L'X') {\r
+ if (!LeadingZero) {\r
+ //\r
+ // we got an x without a preceeding 0\r
+ //\r
+ return (FALSE);\r
+ }\r
+ String++;\r
+ Hex = TRUE;\r
+ } else if (ForceHex) {\r
+ Hex = TRUE;\r
+ } else {\r
+ Hex = FALSE;\r
+ }\r
+\r
+ //\r
+ // loop through the remaining characters and use the lib function\r
+ //\r
+ for ( ; *String != CHAR_NULL && !(StopAtSpace && *String == L' ') ; String++){\r
+ if (TimeNumbers && (String[0] == L':')) {\r
+ continue;\r
+ }\r
+ if (Hex) {\r
+ if (!ShellIsHexaDecimalDigitCharacter(*String)) {\r
+ return (FALSE);\r
+ }\r
+ } else {\r
+ if (!ShellIsDecimalDigitCharacter(*String)) {\r
+ return (FALSE);\r
+ }\r
+ }\r
+ }\r
+\r
+ return (TRUE);\r
}\r
+\r
+/**\r
+ Function to determine if a given filename exists.\r
+\r
+ @param[in] Name Path to test.\r
+\r
+ @retval EFI_SUCCESS The Path represents a file.\r
+ @retval EFI_NOT_FOUND The Path does not represent a file.\r
+ @retval other The path failed to open.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFileExists(\r
+ IN CONST CHAR16 *Name\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SHELL_FILE_INFO *List;\r
+\r
+ ASSERT(Name != NULL);\r
+\r
+ List = NULL;\r
+ Status = ShellOpenFileMetaArg((CHAR16*)Name, EFI_FILE_MODE_READ, &List);\r
+ if (EFI_ERROR(Status)) {\r
+ return (Status);\r
+ }\r
+\r
+ ShellCloseFileMetaArg(&List);\r
+\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ Convert a Unicode character to numerical value.\r
+\r
+ This internal function only deal with Unicode character\r
+ which maps to a valid hexadecimal ASII character, i.e.\r
+ L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other\r
+ Unicode character, the value returned does not make sense.\r
+\r
+ @param Char The character to convert.\r
+\r
+ @return The numerical value converted.\r
+\r
+**/\r
+UINTN\r
+InternalShellHexCharToUintn (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ if (ShellIsDecimalDigitCharacter (Char)) {\r
+ return Char - L'0';\r
+ }\r
+\r
+ return (10 + CharToUpper (Char) - L'A');\r
+}\r
+\r
+/**\r
+ Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.\r
+\r
+ This function returns a value of type UINT64 by interpreting the contents\r
+ of the Unicode string specified by String as a hexadecimal number.\r
+ The format of the input Unicode string String is:\r
+\r
+ [spaces][zeros][x][hexadecimal digits].\r
+\r
+ The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].\r
+ The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.\r
+ If "x" appears in the input string, it must be prefixed with at least one 0.\r
+ The function will ignore the pad space, which includes spaces or tab characters,\r
+ before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or\r
+ [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the\r
+ first valid hexadecimal digit. Then, the function stops at the first character that is\r
+ a not a valid hexadecimal character or NULL, whichever one comes first.\r
+\r
+ If String has only pad spaces, then zero is returned.\r
+ If String has no leading pad spaces, leading zeros or valid hexadecimal digits,\r
+ then zero is returned.\r
+\r
+ @param[in] String A pointer to a Null-terminated Unicode string.\r
+ @param[out] Value Upon a successful return the value of the conversion.\r
+ @param[in] StopAtSpace FALSE to skip spaces.\r
+\r
+ @retval EFI_SUCCESS The conversion was successful.\r
+ @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.\r
+ @retval EFI_DEVICE_ERROR An overflow occurred.\r
+**/\r
+EFI_STATUS\r
+InternalShellStrHexToUint64 (\r
+ IN CONST CHAR16 *String,\r
+ OUT UINT64 *Value,\r
+ IN CONST BOOLEAN StopAtSpace\r
+ )\r
+{\r
+ UINT64 Result;\r
+\r
+ if (String == NULL || StrSize(String) == 0 || Value == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
+ //\r
+ // Ignore the pad spaces (space or tab)\r
+ //\r
+ while ((*String == L' ') || (*String == L'\t')) {\r
+ String++;\r
+ }\r
+\r
+ //\r
+ // Ignore leading Zeros after the spaces\r
+ //\r
+ while (*String == L'0') {\r
+ String++;\r
+ }\r
+\r
+ if (CharToUpper (*String) == L'X') {\r
+ if (*(String - 1) != L'0') {\r
+ return 0;\r
+ }\r
+ //\r
+ // Skip the 'X'\r
+ //\r
+ String++;\r
+ }\r
+\r
+ Result = 0;\r
+\r
+ //\r
+ // there is a space where there should't be\r
+ //\r
+ if (*String == L' ') {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
+ while (ShellIsHexaDecimalDigitCharacter (*String)) {\r
+ //\r
+ // If the Hex Number represented by String overflows according\r
+ // to the range defined by UINT64, then return EFI_DEVICE_ERROR.\r
+ //\r
+ if (!(Result <= (RShiftU64((((UINT64) ~0) - InternalShellHexCharToUintn (*String)), 4)))) {\r
+// if (!(Result <= ((((UINT64) ~0) - InternalShellHexCharToUintn (*String)) >> 4))) {\r
+ return (EFI_DEVICE_ERROR);\r
+ }\r
+\r
+ Result = (LShiftU64(Result, 4));\r
+ Result += InternalShellHexCharToUintn (*String);\r
+ String++;\r
+\r
+ //\r
+ // stop at spaces if requested\r
+ //\r
+ if (StopAtSpace && *String == L' ') {\r
+ break;\r
+ }\r
+ }\r
+\r
+ *Value = Result;\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ Convert a Null-terminated Unicode decimal string to a value of\r
+ type UINT64.\r
+\r
+ This function returns a value of type UINT64 by interpreting the contents\r
+ of the Unicode string specified by String as a decimal number. The format\r
+ of the input Unicode string String is:\r
+\r
+ [spaces] [decimal digits].\r
+\r
+ The valid decimal digit character is in the range [0-9]. The\r
+ function will ignore the pad space, which includes spaces or\r
+ tab characters, before [decimal digits]. The running zero in the\r
+ beginning of [decimal digits] will be ignored. Then, the function\r
+ stops at the first character that is a not a valid decimal character\r
+ or a Null-terminator, whichever one comes first.\r
+\r
+ If String has only pad spaces, then 0 is returned.\r
+ If String has no pad spaces or valid decimal digits,\r
+ then 0 is returned.\r
+\r
+ @param[in] String A pointer to a Null-terminated Unicode string.\r
+ @param[out] Value Upon a successful return the value of the conversion.\r
+ @param[in] StopAtSpace FALSE to skip spaces.\r
+\r
+ @retval EFI_SUCCESS The conversion was successful.\r
+ @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.\r
+ @retval EFI_DEVICE_ERROR An overflow occurred.\r
+**/\r
+EFI_STATUS\r
+InternalShellStrDecimalToUint64 (\r
+ IN CONST CHAR16 *String,\r
+ OUT UINT64 *Value,\r
+ IN CONST BOOLEAN StopAtSpace\r
+ )\r
+{\r
+ UINT64 Result;\r
+\r
+ if (String == NULL || StrSize (String) == 0 || Value == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
+ //\r
+ // Ignore the pad spaces (space or tab)\r
+ //\r
+ while ((*String == L' ') || (*String == L'\t')) {\r
+ String++;\r
+ }\r
+\r
+ //\r
+ // Ignore leading Zeros after the spaces\r
+ //\r
+ while (*String == L'0') {\r
+ String++;\r
+ }\r
+\r
+ Result = 0;\r
+\r
+ //\r
+ // Stop upon space if requested\r
+ // (if the whole value was 0)\r
+ //\r
+ if (StopAtSpace && *String == L' ') {\r
+ *Value = Result;\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ while (ShellIsDecimalDigitCharacter (*String)) {\r
+ //\r
+ // If the number represented by String overflows according\r
+ // to the range defined by UINT64, then return EFI_DEVICE_ERROR.\r
+ //\r
+\r
+ if (!(Result <= (DivU64x32((((UINT64) ~0) - (*String - L'0')),10)))) {\r
+ return (EFI_DEVICE_ERROR);\r
+ }\r
+\r
+ Result = MultU64x32(Result, 10) + (*String - L'0');\r
+ String++;\r
+\r
+ //\r
+ // Stop at spaces if requested\r
+ //\r
+ if (StopAtSpace && *String == L' ') {\r
+ break;\r
+ }\r
+ }\r
+\r
+ *Value = Result;\r
+\r
+ return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+ Function to verify and convert a string to its numerical value.\r
+\r
+ If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE.\r
+\r
+ @param[in] String The string to evaluate.\r
+ @param[out] Value Upon a successful return the value of the conversion.\r
+ @param[in] ForceHex TRUE - always assume hex.\r
+ @param[in] StopAtSpace FALSE to skip spaces.\r
+\r
+ @retval EFI_SUCCESS The conversion was successful.\r
+ @retval EFI_INVALID_PARAMETER String contained an invalid character.\r
+ @retval EFI_NOT_FOUND String was a number, but Value was NULL.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellConvertStringToUint64(\r
+ IN CONST CHAR16 *String,\r
+ OUT UINT64 *Value,\r
+ IN CONST BOOLEAN ForceHex,\r
+ IN CONST BOOLEAN StopAtSpace\r
+ )\r
+{\r
+ UINT64 RetVal;\r
+ CONST CHAR16 *Walker;\r
+ EFI_STATUS Status;\r
+ BOOLEAN Hex;\r
+\r
+ Hex = ForceHex;\r
+\r
+ if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {\r
+ if (!Hex) {\r
+ Hex = TRUE;\r
+ if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ } else {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Chop off leading spaces\r
+ //\r
+ for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);\r
+\r
+ //\r
+ // make sure we have something left that is numeric.\r
+ //\r
+ if (Walker == NULL || *Walker == CHAR_NULL || !InternalShellIsHexOrDecimalNumber(Walker, Hex, StopAtSpace, FALSE)) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
+ //\r
+ // do the conversion.\r
+ //\r
+ if (Hex || StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){\r
+ Status = InternalShellStrHexToUint64(Walker, &RetVal, StopAtSpace);\r
+ } else {\r
+ Status = InternalShellStrDecimalToUint64(Walker, &RetVal, StopAtSpace);\r
+ }\r
+\r
+ if (Value == NULL && !EFI_ERROR(Status)) {\r
+ return (EFI_NOT_FOUND);\r
+ }\r
+\r
+ if (Value != NULL) {\r
+ *Value = RetVal;\r
+ }\r
+\r
+ return (Status);\r
+}\r
+\r
+/**\r
+ Function to determin if an entire string is a valid number.\r
+\r
+ If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.\r
+\r
+ @param[in] String The string to evaluate.\r
+ @param[in] ForceHex TRUE - always assume hex.\r
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.\r
+\r
+ @retval TRUE It is all numeric (dec/hex) characters.\r
+ @retval FALSE There is a non-numeric character.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ShellIsHexOrDecimalNumber (\r
+ IN CONST CHAR16 *String,\r
+ IN CONST BOOLEAN ForceHex,\r
+ IN CONST BOOLEAN StopAtSpace\r
+ )\r
+{\r
+ if (ShellConvertStringToUint64(String, NULL, ForceHex, StopAtSpace) == EFI_NOT_FOUND) {\r
+ return (TRUE);\r
+ }\r
+ return (FALSE);\r
+}\r
+\r
+/**\r
+ Function to read a single line from a SHELL_FILE_HANDLE. The \n is not included in the returned\r
+ buffer. The returned buffer must be callee freed.\r
+\r
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be\r
+ maintained and not changed for all operations with the same file.\r
+\r
+ @param[in] Handle SHELL_FILE_HANDLE to read from.\r
+ @param[in, out] Ascii Boolean value for indicating whether the file is\r
+ Ascii (TRUE) or UCS2 (FALSE).\r
+\r
+ @return The line of text from the file.\r
+ @retval NULL There was not enough memory available.\r
+\r
+ @sa ShellFileHandleReadLine\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+ShellFileHandleReturnLine(\r
+ IN SHELL_FILE_HANDLE Handle,\r
+ IN OUT BOOLEAN *Ascii\r
+ )\r
+{\r
+ CHAR16 *RetVal;\r
+ UINTN Size;\r
+ EFI_STATUS Status;\r
+\r
+ Size = 0;\r
+ RetVal = NULL;\r
+\r
+ Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ RetVal = AllocateZeroPool(Size);\r
+ if (RetVal == NULL) {\r
+ return (NULL);\r
+ }\r
+ Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);\r
+\r
+ }\r
+ if (Status == EFI_END_OF_FILE && RetVal != NULL && *RetVal != CHAR_NULL) {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ if (EFI_ERROR(Status) && (RetVal != NULL)) {\r
+ FreePool(RetVal);\r
+ RetVal = NULL;\r
+ }\r
+ return (RetVal);\r
+}\r
+\r
+/**\r
+ Function to read a single line (up to but not including the \n) from a SHELL_FILE_HANDLE.\r
+\r
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be\r
+ maintained and not changed for all operations with the same file.\r
+\r
+ NOTE: LINES THAT ARE RETURNED BY THIS FUNCTION ARE UCS2, EVEN IF THE FILE BEING READ\r
+ IS IN ASCII FORMAT.\r
+\r
+ @param[in] Handle SHELL_FILE_HANDLE to read from.\r
+ @param[in, out] Buffer The pointer to buffer to read into. If this function\r
+ returns EFI_SUCCESS, then on output Buffer will\r
+ contain a UCS2 string, even if the file being\r
+ read is ASCII.\r
+ @param[in, out] Size On input, pointer to number of bytes in Buffer.\r
+ On output, unchanged unless Buffer is too small\r
+ to contain the next line of the file. In that\r
+ case Size is set to the number of bytes needed\r
+ to hold the next line of the file (as a UCS2\r
+ string, even if it is an ASCII file).\r
+ @param[in] Truncate If the buffer is large enough, this has no effect.\r
+ If the buffer is is too small and Truncate is TRUE,\r
+ the line will be truncated.\r
+ If the buffer is is too small and Truncate is FALSE,\r
+ then no read will occur.\r
+\r
+ @param[in, out] Ascii Boolean value for indicating whether the file is\r
+ Ascii (TRUE) or UCS2 (FALSE).\r
+\r
+ @retval EFI_SUCCESS The operation was successful. The line is stored in\r
+ Buffer.\r
+ @retval EFI_END_OF_FILE There are no more lines in the file.\r
+ @retval EFI_INVALID_PARAMETER Handle was NULL.\r
+ @retval EFI_INVALID_PARAMETER Size was NULL.\r
+ @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line.\r
+ Size was updated to the minimum space required.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellFileHandleReadLine(\r
+ IN SHELL_FILE_HANDLE Handle,\r
+ IN OUT CHAR16 *Buffer,\r
+ IN OUT UINTN *Size,\r
+ IN BOOLEAN Truncate,\r
+ IN OUT BOOLEAN *Ascii\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 CharBuffer;\r
+ UINTN CharSize;\r
+ UINTN CountSoFar;\r
+ UINT64 OriginalFilePosition;\r
+\r
+\r
+ if (Handle == NULL\r
+ ||Size == NULL\r
+ ){\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+ if (Buffer == NULL) {\r
+ ASSERT(*Size == 0);\r
+ } else {\r
+ *Buffer = CHAR_NULL;\r
+ }\r
+ gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
+ if (OriginalFilePosition == 0) {\r
+ CharSize = sizeof(CHAR16);\r
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
+ ASSERT_EFI_ERROR(Status);\r
+ if (CharBuffer == gUnicodeFileTag) {\r
+ *Ascii = FALSE;\r
+ } else {\r
+ *Ascii = TRUE;\r
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
+ }\r
+ }\r
+\r
+ if (*Ascii) {\r
+ CharSize = sizeof(CHAR8);\r
+ } else {\r
+ CharSize = sizeof(CHAR16);\r
+ }\r
+ for (CountSoFar = 0;;CountSoFar++){\r
+ CharBuffer = 0;\r
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
+ if ( EFI_ERROR(Status)\r
+ || CharSize == 0\r
+ || (CharBuffer == L'\n' && !(*Ascii))\r
+ || (CharBuffer == '\n' && *Ascii)\r
+ ){\r
+ if (CharSize == 0) {\r
+ Status = EFI_END_OF_FILE;\r
+ }\r
+ break;\r
+ }\r
+ //\r
+ // if we have space save it...\r
+ //\r
+ if ((CountSoFar+1)*sizeof(CHAR16) < *Size){\r
+ ASSERT(Buffer != NULL);\r
+ ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;\r
+ ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // if we ran out of space tell when...\r
+ //\r
+ if ((CountSoFar+1)*sizeof(CHAR16) > *Size){\r
+ *Size = (CountSoFar+1)*sizeof(CHAR16);\r
+ if (!Truncate) {\r
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
+ } else {\r
+ DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));\r
+ }\r
+ return (EFI_BUFFER_TOO_SMALL);\r
+ }\r
+ while(Buffer[StrLen(Buffer)-1] == L'\r') {\r
+ Buffer[StrLen(Buffer)-1] = CHAR_NULL;\r
+ }\r
+\r
+ return (Status);\r
+}\r
+\r
+/**\r
+ Function to print help file / man page content in the spec from the UEFI Shell protocol GetHelpText function.\r
+\r
+ @param[in] CommandToGetHelpOn Pointer to a string containing the command name of help file to be printed.\r
+ @param[in] SectionToGetHelpOn Pointer to the section specifier(s).\r
+ @param[in] PrintCommandText If TRUE, prints the command followed by the help content, otherwise prints\r
+ the help content only.\r
+ @retval EFI_DEVICE_ERROR The help data format was incorrect.\r
+ @retval EFI_NOT_FOUND The help data could not be found.\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellPrintHelp (\r
+ IN CONST CHAR16 *CommandToGetHelpOn,\r
+ IN CONST CHAR16 *SectionToGetHelpOn,\r
+ IN BOOLEAN PrintCommandText\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *OutText;\r
+\r
+ OutText = NULL;\r
+\r
+ //\r
+ // Get the string to print based\r
+ //\r
+ Status = gEfiShellProtocol->GetHelpText (CommandToGetHelpOn, SectionToGetHelpOn, &OutText);\r
+\r
+ //\r
+ // make sure we got a valid string\r
+ //\r
+ if (EFI_ERROR(Status)){\r
+ return Status;\r
+ }\r
+ if (OutText == NULL || StrLen(OutText) == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ //\r
+ // Chop off trailing stuff we dont need\r
+ //\r
+ while (OutText[StrLen(OutText)-1] == L'\r' || OutText[StrLen(OutText)-1] == L'\n' || OutText[StrLen(OutText)-1] == L' ') {\r
+ OutText[StrLen(OutText)-1] = CHAR_NULL;\r
+ }\r
+\r
+ //\r
+ // Print this out to the console\r
+ //\r
+ if (PrintCommandText) {\r
+ ShellPrintEx(-1, -1, L"%H%-14s%N- %s\r\n", CommandToGetHelpOn, OutText);\r
+ } else {\r
+ ShellPrintEx(-1, -1, L"%N%s\r\n", OutText);\r
+ }\r
+\r
+ SHELL_FREE_NON_NULL(OutText);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Function to delete a file by name\r
+\r
+ @param[in] FileName Pointer to file name to delete.\r
+\r
+ @retval EFI_SUCCESS the file was deleted sucessfully\r
+ @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not\r
+ deleted\r
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
+ @retval EFI_NOT_FOUND The specified file could not be found on the\r
+ device or the file system could not be found\r
+ 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\r
+ medium is no longer supported.\r
+ @retval EFI_DEVICE_ERROR The device reported an error.\r
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.\r
+ @retval EFI_ACCESS_DENIED The file was opened read only.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
+ file.\r
+ @retval other The file failed to open\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellDeleteFileByName(\r
+ IN CONST CHAR16 *FileName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ SHELL_FILE_HANDLE FileHandle;\r
+\r
+ Status = ShellFileExists(FileName);\r
+\r
+ if (Status == EFI_SUCCESS){\r
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0x0);\r
+ if (Status == EFI_SUCCESS){\r
+ Status = ShellDeleteFile(&FileHandle);\r
+ }\r
+ }\r
+\r
+ return(Status);\r
+\r
+}\r
+\r
+/**\r
+ Cleans off all the quotes in the string.\r
+\r
+ @param[in] OriginalString pointer to the string to be cleaned.\r
+ @param[out] CleanString The new string with all quotes removed.\r
+ Memory allocated in the function and free\r
+ by caller.\r
+\r
+ @retval EFI_SUCCESS The operation was successful.\r
+**/\r
+EFI_STATUS\r
+InternalShellStripQuotes (\r
+ IN CONST CHAR16 *OriginalString,\r
+ OUT CHAR16 **CleanString\r
+ )\r
+{\r
+ CHAR16 *Walker;\r
+\r
+ if (OriginalString == NULL || CleanString == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString);\r
+ if (*CleanString == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {\r
+ if (*Walker == L'\"') {\r
+ CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r