+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
+ 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
+ //\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
+\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
+ //\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