]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellLib/UefiShellLib.c
Adding new library instance for SortLib with built in function for sorting device...
[mirror_edk2.git] / ShellPkg / Library / UefiShellLib / UefiShellLib.c
index 20805725fcec08578277bbdb393c6991d75449e5..0d79880dffb026b71f7d0d84e969e0a63562d447 100644 (file)
@@ -24,6 +24,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/FileHandleLib.h>\r
 #include <Library/PrintLib.h>\r
 #include <Library/UefiLib.h>\r
+#include <Library/HiiLib.h>\r
 \r
 #include <Protocol/EfiShellEnvironment2.h>\r
 #include <Protocol/EfiShellInterface.h>\r
@@ -52,6 +53,29 @@ STATIC EFI_SHELL_PROTOCOL            *mEfiShellProtocol;
 STATIC EFI_SHELL_PARAMETERS_PROTOCOL *mEfiShellParametersProtocol;\r
 STATIC EFI_HANDLE                    mEfiShellEnvironment2Handle;\r
 STATIC FILE_HANDLE_FUNCTION_MAP      FileFunctionMap;\r
+STATIC UINTN                         mTotalParameterCount;\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
+  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
+  @retval FALSE If the Char is not a hexadecmial character.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ShellInternalIsHexaDecimalDigitCharacter (\r
+  IN      CHAR16                    Char\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
@@ -60,8 +84,7 @@ EFI_STATUS
 EFIAPI\r
 ShellFindSE2 (\r
   IN EFI_HANDLE        ImageHandle\r
-  )\r
-{\r
+  ) {\r
   EFI_STATUS  Status;\r
   EFI_HANDLE  *Buffer;\r
   UINTN       BufferSize;\r
@@ -79,9 +102,7 @@ ShellFindSE2 (
   //\r
   // look for the mEfiShellEnvironment2 protocol at a higher level\r
   //\r
-  if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE &&\r
-     (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER ||\r
-     (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER)))) {\r
+  if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE)){\r
     //\r
     // figure out how big of a buffer we need.\r
     //\r
@@ -91,15 +112,19 @@ ShellFindSE2 (
                                 &BufferSize,\r
                                 Buffer\r
                                 );\r
-    ASSERT(Status == EFI_BUFFER_TOO_SMALL);\r
-    Buffer = (EFI_HANDLE*)AllocatePool(BufferSize);\r
-    ASSERT(Buffer != NULL);\r
-    Status = gBS->LocateHandle (ByProtocol,\r
-                                &gEfiShellEnvironment2Guid,\r
-                                NULL, // ignored for ByProtocol\r
-                                &BufferSize,\r
-                                Buffer\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
+      Status = gBS->LocateHandle (ByProtocol,\r
+                                  &gEfiShellEnvironment2Guid,\r
+                                  NULL, // ignored for ByProtocol\r
+                                  &BufferSize,\r
+                                  Buffer\r
+                                  );\r
+    }\r
     if (!EFI_ERROR (Status)) {\r
       //\r
       // now parse the list of returned handles\r
@@ -113,9 +138,7 @@ ShellFindSE2 (
                                    NULL,\r
                                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                                    );\r
-         if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE &&\r
-          (mEfiShellEnvironment2->MajorVersion > EFI_SHELL_MAJOR_VER ||\r
-          (mEfiShellEnvironment2->MajorVersion == EFI_SHELL_MAJOR_VER && mEfiShellEnvironment2->MinorVersion >= EFI_SHELL_MINOR_VER))) {\r
+         if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid) != FALSE) {\r
           mEfiShellEnvironment2Handle = Buffer[HandleIndex];\r
           Status = EFI_SUCCESS;\r
           break;\r
@@ -134,9 +157,14 @@ EFIAPI
 ShellLibConstructorWorker (\r
   IN EFI_HANDLE        ImageHandle,\r
   IN EFI_SYSTEM_TABLE  *SystemTable\r
-){\r
+  ) {\r
   EFI_STATUS Status;\r
 \r
+  //\r
+  // Set the parameter count to an invalid number\r
+  //\r
+  mTotalParameterCount = (UINTN)(-1);\r
+\r
   //\r
   // UEFI 2.0 shell interfaces (used preferentially)\r
   //\r
@@ -230,8 +258,7 @@ EFIAPI
 ShellLibConstructor (\r
   IN EFI_HANDLE        ImageHandle,\r
   IN EFI_SYSTEM_TABLE  *SystemTable\r
-  )\r
-{\r
+  ) {\r
 \r
 \r
   mEfiShellEnvironment2       = NULL;\r
@@ -258,7 +285,7 @@ EFIAPI
 ShellLibDestructor (\r
   IN EFI_HANDLE        ImageHandle,\r
   IN EFI_SYSTEM_TABLE  *SystemTable\r
-  ){\r
+  ) {\r
   if (mEfiShellEnvironment2 != NULL) {\r
     gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,\r
                        &gEfiShellEnvironment2Guid,\r
@@ -344,8 +371,7 @@ EFI_FILE_INFO*
 EFIAPI\r
 ShellGetFileInfo (\r
   IN EFI_FILE_HANDLE            FileHandle\r
-  )\r
-{\r
+  ) {\r
   return (FileFunctionMap.GetFileInfo(FileHandle));\r
 }\r
 \r
@@ -372,8 +398,7 @@ EFIAPI
 ShellSetFileInfo (\r
   IN EFI_FILE_HANDLE           FileHandle,\r
   IN EFI_FILE_INFO              *FileInfo\r
-  )\r
-{\r
+  ) {\r
   return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo));\r
 }  \r
   \r
@@ -415,8 +440,7 @@ ShellOpenFileByDevicePath(
   OUT EFI_FILE_HANDLE                  *FileHandle,\r
   IN UINT64                            OpenMode,\r
   IN UINT64                            Attributes\r
-  )\r
-{\r
+  ) {\r
   CHAR16      *FileName;\r
   EFI_STATUS  Status;\r
   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;\r
@@ -566,8 +590,7 @@ ShellOpenFileByName(
   OUT EFI_FILE_HANDLE           *FileHandle,\r
   IN UINT64                     OpenMode,\r
   IN UINT64                            Attributes\r
-  )\r
-{\r
+  ) {\r
   EFI_HANDLE                    DeviceHandle;\r
   EFI_DEVICE_PATH_PROTOCOL      *FilePath;\r
   EFI_STATUS                    Status;\r
@@ -585,11 +608,12 @@ ShellOpenFileByName(
     Status = mEfiShellProtocol->OpenFileByName(FileName,\r
                                                FileHandle,\r
                                                OpenMode);\r
-    if (!EFI_ERROR(Status)){\r
-      FileInfo = FileHandleGetInfo(*FileHandle);\r
+    if (!EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){\r
+      FileInfo = FileFunctionMap.GetFileInfo(*FileHandle);\r
       ASSERT(FileInfo != NULL);\r
       FileInfo->Attribute = Attributes;\r
-      Status = FileHandleSetInfo(*FileHandle, FileInfo);\r
+      Status = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);\r
+      FreePool(FileInfo);\r
     }\r
     return (Status);\r
   } \r
@@ -642,16 +666,22 @@ EFIAPI
 ShellCreateDirectory(\r
   IN CONST CHAR16             *DirectoryName,\r
   OUT EFI_FILE_HANDLE         *FileHandle\r
-  )\r
-{\r
-  //\r
-  // this is a pass thru to the open file function with sepcific open mode and attributes\r
-  //\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
+  if (mEfiShellProtocol != NULL) {\r
+    //\r
+    // Use UEFI Shell 2.0 method\r
+    //\r
+    return (mEfiShellProtocol->CreateFile(DirectoryName,\r
+                          EFI_FILE_DIRECTORY,\r
+                          FileHandle\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
@@ -689,8 +719,7 @@ ShellReadFile(
   IN EFI_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
@@ -725,8 +754,7 @@ ShellWriteFile(
   IN EFI_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
@@ -745,8 +773,7 @@ EFI_STATUS
 EFIAPI\r
 ShellCloseFile (\r
   IN EFI_FILE_HANDLE            *FileHandle\r
-  )\r
-{\r
+  ) {\r
   return (FileFunctionMap.CloseFile(*FileHandle));\r
 }\r
 \r
@@ -768,8 +795,7 @@ EFI_STATUS
 EFIAPI\r
 ShellDeleteFile (\r
   IN EFI_FILE_HANDLE           *FileHandle\r
-  )\r
-{\r
+  ) {\r
   return (FileFunctionMap.DeleteFile(*FileHandle));\r
 }\r
 \r
@@ -797,8 +823,7 @@ EFIAPI
 ShellSetFilePosition (\r
   IN EFI_FILE_HANDLE           FileHandle,\r
   IN UINT64            Position\r
-  )\r
-{\r
+  ) {\r
   return (FileFunctionMap.SetFilePosition(FileHandle, Position));\r
 }\r
 \r
@@ -822,8 +847,7 @@ EFIAPI
 ShellGetFilePosition (\r
   IN EFI_FILE_HANDLE            FileHandle,\r
   OUT UINT64                    *Position\r
-  )\r
-{\r
+  ) {\r
   return (FileFunctionMap.GetFilePosition(FileHandle, Position));\r
 }\r
 /**\r
@@ -844,8 +868,7 @@ EFI_STATUS
 EFIAPI\r
 ShellFlushFile (\r
   IN EFI_FILE_HANDLE            FileHandle\r
-  )\r
-{\r
+  ) {\r
   return (FileFunctionMap.FlushFile(FileHandle));\r
 }\r
 \r
@@ -872,8 +895,7 @@ EFIAPI
 ShellFindFirstFile (\r
   IN EFI_FILE_HANDLE            DirHandle,\r
   OUT EFI_FILE_INFO             **Buffer\r
-  )\r
-{\r
+  ) {\r
   //\r
   // pass to file handle lib\r
   //\r
@@ -904,8 +926,7 @@ ShellFindNextFile(
   IN EFI_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
@@ -931,8 +952,7 @@ EFIAPI
 ShellGetFileSize (\r
   IN EFI_FILE_HANDLE            FileHandle,\r
   OUT UINT64                    *Size\r
-  )\r
-{\r
+  ) {\r
   return (FileFunctionMap.GetFileSize(FileHandle, Size));\r
 }\r
 /**\r
@@ -1306,7 +1326,8 @@ InternalShellConvertFileListType (
   and will process '?' and '*' as such.  the list must be freed with a call to \r
   ShellCloseFileMetaArg().\r
 \r
-  If you are NOT appending to an existing list *ListHead must be NULL.\r
+  If you are NOT appending to an existing list *ListHead must be NULL.  If \r
+  *ListHead is NULL then it must be callee freed.\r
 \r
   @param Arg                    pointer to path string\r
   @param OpenMode               mode to open files with\r
@@ -1341,9 +1362,22 @@ ShellOpenFileMetaArg (
   // Check for UEFI Shell 2.0 protocols\r
   //\r
   if (mEfiShellProtocol != NULL) {\r
-    return (mEfiShellProtocol->OpenFileList(Arg, \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
+      }\r
+      InitializeListHead(&((*ListHead)->Link));\r
+    }    \r
+    Status = mEfiShellProtocol->OpenFileList(Arg, \r
                                            OpenMode, \r
-                                           ListHead));\r
+                                           ListHead);\r
+    if (EFI_ERROR(Status)) {\r
+      mEfiShellProtocol->RemoveDupInFileList(ListHead);\r
+    } else {\r
+      Status = mEfiShellProtocol->RemoveDupInFileList(ListHead);\r
+    }\r
+    return (Status);\r
   } \r
 \r
   //\r
@@ -1459,8 +1493,7 @@ InternalIsOnCheckList (
   IN CONST CHAR16               *Name,\r
   IN CONST SHELL_PARAM_ITEM     *CheckList,\r
   OUT ParamType                 *Type\r
-  )\r
-{\r
+  ) {\r
   SHELL_PARAM_ITEM              *TempListItem;\r
 \r
   //\r
@@ -1484,13 +1517,18 @@ InternalIsOnCheckList (
   //\r
   for (TempListItem = (SHELL_PARAM_ITEM*)CheckList ; TempListItem->Name != NULL ; TempListItem++) {\r
     //\r
-    // If the Name matches set the type and return TRUE\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 (StrCmp(Name, TempListItem->Name) == 0) {\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
       *Type = TempListItem->Type;\r
       return (TRUE);\r
     }\r
   }\r
+\r
   return (FALSE);\r
 }\r
 /**\r
@@ -1504,7 +1542,8 @@ InternalIsOnCheckList (
 BOOLEAN\r
 EFIAPI\r
 InternalIsFlag (\r
-  IN CONST CHAR16               *Name\r
+  IN CONST CHAR16               *Name,\r
+  IN BOOLEAN                    AlwaysAllowNumbers\r
   )\r
 {\r
   //\r
@@ -1512,6 +1551,13 @@ InternalIsFlag (
   //\r
   ASSERT(Name != NULL);\r
 \r
+  //\r
+  // If we accept numbers then dont return TRUE. (they will be values)\r
+  //\r
+  if (((Name[0] == L'-' || Name[0] == L'+') && ShellInternalIsHexaDecimalDigitCharacter(Name[1])) && AlwaysAllowNumbers == TRUE) {\r
+    return (FALSE);\r
+  }\r
+\r
   //\r
   // If the Name has a / or - as the first character return TRUE\r
   //\r
@@ -1548,6 +1594,7 @@ InternalIsFlag (
                                 the invalid command line argument was returned in\r
                                 ProblemParam if provided.\r
 **/\r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 InternalCommandLineParse (\r
@@ -1556,24 +1603,16 @@ InternalCommandLineParse (
   OUT CHAR16                    **ProblemParam OPTIONAL,\r
   IN BOOLEAN                    AutoPageBreak,\r
   IN CONST CHAR16               **Argv,\r
-  IN UINTN                      Argc\r
-  )\r
-{\r
+  IN UINTN                      Argc,\r
+  IN BOOLEAN                    AlwaysAllowNumbers\r
+  ) {\r
   UINTN                         LoopCounter;\r
-  UINTN                         Count;\r
   ParamType                     CurrentItemType;\r
   SHELL_PARAM_PACKAGE           *CurrentItemPackage;\r
   BOOLEAN                       GetItemValue;\r
 \r
   CurrentItemPackage = NULL;\r
-\r
-  //\r
-  // ASSERTs\r
-  //\r
-  ASSERT(CheckList  != NULL);\r
-  ASSERT(Argv       != NULL);\r
-\r
-  Count = 0;\r
+  mTotalParameterCount = 0;\r
   GetItemValue = FALSE;\r
 \r
   //\r
@@ -1584,6 +1623,12 @@ InternalCommandLineParse (
     return (EFI_SUCCESS);\r
   }\r
 \r
+  //\r
+  // ASSERTs\r
+  //\r
+  ASSERT(CheckList  != NULL);\r
+  ASSERT(Argv       != NULL);\r
+\r
   //\r
   // initialize the linked list\r
   //\r
@@ -1599,6 +1644,13 @@ InternalCommandLineParse (
       // do nothing for NULL argv\r
       //\r
     } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType) == TRUE) {\r
+      //\r
+      // We might have leftover if last parameter didnt have optional value\r
+      //\r
+      if (GetItemValue == TRUE) {\r
+        GetItemValue = FALSE;\r
+        InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
+      }\r
       //\r
       // this is a flag\r
       //\r
@@ -1625,7 +1677,7 @@ InternalCommandLineParse (
         //\r
         InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
       }\r
-    } else if (GetItemValue == TRUE && InternalIsFlag(Argv[LoopCounter]) == FALSE) {\r
+    } else if (GetItemValue == TRUE && InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) == FALSE) {\r
       ASSERT(CurrentItemPackage != NULL);\r
       //\r
       // get the item VALUE for the previous flag\r
@@ -1635,7 +1687,7 @@ InternalCommandLineParse (
       ASSERT(CurrentItemPackage->Value != NULL);\r
       StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
       InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
-    } else if (InternalIsFlag(Argv[LoopCounter]) == FALSE) {\r
+    } else if (InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers) == FALSE) {\r
       //\r
       // add this one as a non-flag\r
       //\r
@@ -1646,7 +1698,7 @@ InternalCommandLineParse (
       CurrentItemPackage->Value = AllocatePool(StrSize(Argv[LoopCounter]));\r
       ASSERT(CurrentItemPackage->Value != NULL);\r
       StrCpy(CurrentItemPackage->Value, Argv[LoopCounter]);\r
-      CurrentItemPackage->OriginalPosition = Count++;\r
+      CurrentItemPackage->OriginalPosition = mTotalParameterCount++;\r
       InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);\r
     } else if (ProblemParam) {\r
       //\r
@@ -1700,13 +1752,13 @@ InternalCommandLineParse (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-ShellCommandLineParse (\r
+ShellCommandLineParseEx (\r
   IN CONST SHELL_PARAM_ITEM     *CheckList,\r
   OUT LIST_ENTRY                **CheckPackage,\r
   OUT CHAR16                    **ProblemParam OPTIONAL,\r
-  IN BOOLEAN                    AutoPageBreak\r
-  )\r
-{\r
+  IN BOOLEAN                    AutoPageBreak,\r
+  IN BOOLEAN                    AlwaysAllowNumbers\r
+  ) {\r
   // \r
   // ASSERT that CheckList and CheckPackage aren't NULL\r
   //\r
@@ -1722,7 +1774,8 @@ ShellCommandLineParse (
                                      ProblemParam, \r
                                      AutoPageBreak, \r
                                      (CONST CHAR16**) mEfiShellParametersProtocol->Argv,\r
-                                     mEfiShellParametersProtocol->Argc ));\r
+                                     mEfiShellParametersProtocol->Argc,\r
+                                     AlwaysAllowNumbers));\r
   }\r
 \r
   // \r
@@ -1734,7 +1787,8 @@ ShellCommandLineParse (
                                    ProblemParam, \r
                                    AutoPageBreak, \r
                                    (CONST CHAR16**) mEfiShellInterface->Argv,\r
-                                   mEfiShellInterface->Argc ));\r
+                                   mEfiShellInterface->Argc,\r
+                                   AlwaysAllowNumbers));\r
 }\r
 \r
 /**\r
@@ -1753,8 +1807,7 @@ VOID
 EFIAPI\r
 ShellCommandLineFreeVarList (\r
   IN LIST_ENTRY                 *CheckPackage\r
-  )\r
-{\r
+  ) {\r
   LIST_ENTRY                    *Node;\r
 \r
   //\r
@@ -1767,7 +1820,10 @@ ShellCommandLineFreeVarList (
   //\r
   // for each node in the list\r
   //\r
-  for (Node = GetFirstNode(CheckPackage); Node != CheckPackage ; Node = GetFirstNode(CheckPackage)) {\r
+  for ( Node = GetFirstNode(CheckPackage)\r
+      ; IsListEmpty(CheckPackage) == FALSE\r
+      ; Node = GetFirstNode(CheckPackage)\r
+      ){\r
     //\r
     // Remove it from the list\r
     //\r
@@ -1816,8 +1872,7 @@ EFIAPI
 ShellCommandLineGetFlag (\r
   IN CONST LIST_ENTRY           *CheckPackage,\r
   IN CHAR16                     *KeyString\r
-  )\r
-{\r
+  ) {\r
   LIST_ENTRY                    *Node;\r
 \r
   //\r
@@ -1835,12 +1890,22 @@ ShellCommandLineGetFlag (
   //\r
   // enumerate through the list of parametrs\r
   //\r
-  for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) {\r
+  for ( Node = GetFirstNode(CheckPackage) \r
+      ; !IsNull (CheckPackage, Node) \r
+      ; Node = GetNextNode(CheckPackage, Node) \r
+      ){\r
     //\r
     // If the Name matches, return TRUE (and there may be NULL name)\r
     //\r
     if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
-      if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\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
         return (TRUE);\r
       }\r
     }\r
@@ -1865,8 +1930,7 @@ EFIAPI
 ShellCommandLineGetValue (\r
   IN CONST LIST_ENTRY           *CheckPackage,\r
   IN CHAR16                     *KeyString\r
-  )\r
-{\r
+  ) {\r
   LIST_ENTRY                    *Node;\r
 \r
   //\r
@@ -1879,12 +1943,28 @@ ShellCommandLineGetValue (
   //\r
   // enumerate through the list of parametrs\r
   //\r
-  for (Node = GetFirstNode(CheckPackage) ; !IsNull (CheckPackage, Node) ; Node = GetNextNode(CheckPackage, Node) ) {\r
+  for ( Node = GetFirstNode(CheckPackage) \r
+      ; !IsNull (CheckPackage, Node) \r
+      ; Node = GetNextNode(CheckPackage, Node) \r
+      ){\r
     //\r
     // If the Name matches, return the value (name can be NULL)\r
     //\r
     if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {\r
-      if (StrCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {\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
         return (((SHELL_PARAM_PACKAGE*)Node)->Value);\r
       }\r
     }\r
@@ -1909,8 +1989,7 @@ EFIAPI
 ShellCommandLineGetRawValue (\r
   IN CONST LIST_ENTRY           *CheckPackage,\r
   IN UINT32                     Position\r
-  )\r
-{\r
+  ) {\r
   LIST_ENTRY                    *Node;\r
 \r
   //\r
@@ -1936,6 +2015,23 @@ ShellCommandLineGetRawValue (
   }\r
   return (NULL);\r
 }\r
+\r
+/**\r
+  returns the number of command line value parameters that were parsed.  \r
+  \r
+  this will not include flags.\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
+  ){\r
+  return (mTotalParameterCount);\r
+}\r
+\r
 /**\r
   This is a find and replace function.  it will return the NewString as a copy of \r
   SourceString with each instance of FindTarget replaced with ReplaceWith.\r
@@ -1967,7 +2063,9 @@ CopyReplace(
   IN UINTN                            NewSize,\r
   IN CONST CHAR16                     *FindTarget,\r
   IN CONST CHAR16                     *ReplaceWith\r
-  ){\r
+  ) \r
+{\r
+  UINTN Size;\r
   if ( (SourceString == NULL)\r
     || (NewString    == NULL)\r
     || (FindTarget   == NULL)\r
@@ -1977,16 +2075,18 @@ CopyReplace(
     ){\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
-  NewString = SetMem16(NewString, NewSize, L'\0');\r
-  while (*SourceString != L'\0') {\r
+  NewString = SetMem16(NewString, NewSize, CHAR_NULL);\r
+  while (*SourceString != CHAR_NULL) {\r
     if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0) {\r
       SourceString += StrLen(FindTarget);\r
-      if (StrSize(NewString) + (StrLen(ReplaceWith)*sizeof(CHAR16)) > NewSize) {\r
+      Size = StrSize(NewString);\r
+      if ((Size + (StrLen(ReplaceWith)*sizeof(CHAR16))) > NewSize) {\r
         return (EFI_BUFFER_TOO_SMALL);\r
       }\r
       StrCat(NewString, ReplaceWith);\r
     } else {\r
-      if (StrSize(NewString) + sizeof(CHAR16) > NewSize) {\r
+      Size = StrSize(NewString);\r
+      if (Size + sizeof(CHAR16) > NewSize) {\r
         return (EFI_BUFFER_TOO_SMALL);\r
       }\r
       StrnCat(NewString, SourceString, 1);\r
@@ -2020,30 +2120,28 @@ CopyReplace(
   @param[in] Row        the row to print at\r
   @param[in] Col        the column 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
 **/\r
 \r
 UINTN\r
 EFIAPI\r
-ShellPrintEx(\r
+InternalShellPrintWorker(\r
   IN INT32                Col OPTIONAL,\r
   IN INT32                Row OPTIONAL,\r
   IN CONST CHAR16         *Format,\r
-  ...\r
-  ){\r
-  VA_LIST           Marker;\r
+  VA_LIST                 Marker\r
+  ) \r
+{\r
   UINTN             BufferSize;\r
   CHAR16            *PostReplaceFormat;\r
   CHAR16            *PostReplaceFormat2;\r
   UINTN             Return;\r
-\r
   EFI_STATUS        Status;\r
   UINTN             NormalAttribute;\r
   CHAR16            *ResumeLocation;\r
   CHAR16            *FormatWalker;\r
-\r
-  VA_START (Marker, Format);\r
   \r
   BufferSize = (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (CHAR16);\r
   PostReplaceFormat = AllocateZeroPool (BufferSize);\r
@@ -2079,13 +2177,13 @@ ShellPrintEx(
 \r
   NormalAttribute = gST->ConOut->Mode->Attribute;\r
   FormatWalker = PostReplaceFormat2;\r
-  while (*FormatWalker != L'\0') {\r
+  while (*FormatWalker != CHAR_NULL) {\r
     //\r
     // Find the next attribute change request\r
     //\r
     ResumeLocation = StrStr(FormatWalker, L"%");\r
     if (ResumeLocation != NULL) {\r
-      *ResumeLocation = L'\0';\r
+      *ResumeLocation = CHAR_NULL;\r
     }\r
     //\r
     // print the current FormatWalker string\r
@@ -2133,4 +2231,134 @@ ShellPrintEx(
   FreePool(PostReplaceFormat2);\r
 \r
   return (Return);\r
-}
\ No newline at end of file
+}\r
+\r
+/**\r
+  Print at a specific location on the screen.\r
+\r
+  This function will move the cursor to a given screen location and print the specified string\r
+  \r
+  If -1 is specified for either the Row or Col the current screen location for BOTH \r
+  will be used.\r
+\r
+  if either Row or Col is out of range for the current console, then ASSERT\r
+  if Format is NULL, then ASSERT\r
+\r
+  In addition to the standard %-based flags as supported by UefiLib Print() this supports \r
+  the following additional flags:\r
+    %N       -   Set output attribute to normal\r
+    %H       -   Set output attribute to highlight\r
+    %E       -   Set output attribute to error\r
+    %B       -   Set output attribute to blue color\r
+    %V       -   Set output attribute to green color\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] Format     the format string\r
+\r
+  @return the number of characters printed to the screen\r
+**/\r
+\r
+UINTN\r
+EFIAPI\r
+ShellPrintEx(\r
+  IN INT32                Col OPTIONAL,\r
+  IN INT32                Row OPTIONAL,\r
+  IN CONST CHAR16         *Format,\r
+  ...\r
+  ) \r
+{\r
+  VA_LIST           Marker;\r
+  VA_START (Marker, Format);\r
+  return (InternalShellPrintWorker(Col, Row, Format, Marker));\r
+}\r
+\r
+/**\r
+  Print at a specific location on the screen.\r
+\r
+  This function will move the cursor to a given screen location, print the specified string, \r
+  and return the cursor to the original locaiton.  \r
+  \r
+  If -1 is specified for either the Row or Col the current screen location for BOTH \r
+  will be used and the cursor's position will not be moved back to an original location.\r
+\r
+  if either Row or Col is out of range for the current console, then ASSERT\r
+  if Format is NULL, then ASSERT\r
+\r
+  In addition to the standard %-based flags as supported by UefiLib Print() this supports \r
+  the following additional flags:\r
+    %N       -   Set output attribute to normal\r
+    %H       -   Set output attribute to highlight\r
+    %E       -   Set output attribute to error\r
+    %B       -   Set output attribute to blue color\r
+    %V       -   Set output attribute to green color\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] HiiFormatStringId  the format string Id for getting from Hii\r
+  @param[in] HiiFormatHandle    the format string Handle for getting from Hii\r
+\r
+  @return the number of characters printed to the screen\r
+**/\r
+UINTN\r
+EFIAPI\r
+ShellPrintHiiEx(\r
+  IN INT32                Col OPTIONAL,\r
+  IN INT32                Row OPTIONAL,\r
+  IN CONST EFI_STRING_ID  HiiFormatStringId,\r
+  IN CONST EFI_HANDLE     HiiFormatHandle,\r
+  ...\r
+  )\r
+{\r
+  VA_LIST           Marker;\r
+  CHAR16            *HiiFormatString;\r
+  UINTN             RetVal;\r
+\r
+  VA_START (Marker, HiiFormatHandle);\r
+  HiiFormatString = HiiGetString(HiiFormatHandle, HiiFormatStringId, NULL);\r
+  ASSERT(HiiFormatString != NULL);\r
+\r
+  RetVal = InternalShellPrintWorker(Col, Row, HiiFormatString, Marker);\r
+\r
+  FreePool(HiiFormatString);\r
+\r
+  return (RetVal);\r
+}\r
+\r
+/**\r
+  Function to determine if a given filename represents a file or a directory.\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
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellIsDirectory(\r
+  IN CONST CHAR16 *DirName\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_FILE_HANDLE   Handle;\r
+\r
+  Handle = NULL;\r
+\r
+  Status = ShellOpenFileByName(DirName, &Handle, EFI_FILE_MODE_READ, 0);\r
+  if (EFI_ERROR(Status)) {\r
+    return (Status);\r
+  }\r
+\r
+  if (FileHandleIsDirectory(Handle) == EFI_SUCCESS) {\r
+    ShellCloseFile(&Handle);\r
+    return (EFI_SUCCESS);\r
+  }\r
+  ShellCloseFile(&Handle);\r
+  return (EFI_NOT_FOUND);\r
+}\r
+\r