]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
ShellPkg: acpiview: Add GT Frame Number validation to GTDT parser
[mirror_edk2.git] / ShellPkg / Library / UefiShellCommandLib / UefiShellCommandLib.c
index ebb84dd55ec1d5405221370d65b9c3b8c1bbb6f3..4635df40bbdc49397a733ac6a17de2b1d7ecb5fc 100644 (file)
@@ -1,15 +1,11 @@
 /** @file\r
   Provides interface to shell internal functions for shell commands.\r
 \r
-  (C) Copyright 2013-2014, Hewlett-Packard Development Company, L.P.\r
-  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>\r
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\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
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -29,10 +25,29 @@ STATIC UINTN                              mFsMaxCount = 0;
 STATIC UINTN                              mBlkMaxCount = 0;\r
 STATIC BUFFER_LIST                        mFileHandleList;\r
 \r
+STATIC CONST CHAR8 Hex[] = {\r
+  '0',\r
+  '1',\r
+  '2',\r
+  '3',\r
+  '4',\r
+  '5',\r
+  '6',\r
+  '7',\r
+  '8',\r
+  '9',\r
+  'A',\r
+  'B',\r
+  'C',\r
+  'D',\r
+  'E',\r
+  'F'\r
+};\r
+\r
 // global variables required by library class.\r
 EFI_UNICODE_COLLATION_PROTOCOL    *gUnicodeCollation            = NULL;\r
 SHELL_MAP_LIST                    gShellMapList;\r
-SHELL_MAP_LIST                    *gShellCurDir                 = NULL;\r
+SHELL_MAP_LIST                    *gShellCurMapping             = NULL;\r
 \r
 CONST CHAR16* SupportLevel[] = {\r
   L"Minimal",\r
@@ -51,14 +66,70 @@ CommandInit(
   VOID\r
   )\r
 {\r
-  EFI_STATUS Status;\r
+  UINTN                           NumHandles;\r
+  EFI_HANDLE                      *Handles;\r
+  EFI_UNICODE_COLLATION_PROTOCOL  *Uc;\r
+  CHAR8                           *BestLanguage;\r
+  UINTN                           Index;\r
+  EFI_STATUS                      Status;\r
+  CHAR8                           *PlatformLang;\r
+\r
+  GetEfiGlobalVariable2 (EFI_PLATFORM_LANG_VARIABLE_NAME, (VOID**)&PlatformLang, NULL);\r
+  if (PlatformLang == NULL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   if (gUnicodeCollation == NULL) {\r
-    Status = gBS->LocateProtocol(&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&gUnicodeCollation);\r
-    if (EFI_ERROR(Status)) {\r
-      return (EFI_DEVICE_ERROR);\r
+    Status = gBS->LocateHandleBuffer (\r
+                    ByProtocol,\r
+                    &gEfiUnicodeCollation2ProtocolGuid,\r
+                    NULL,\r
+                    &NumHandles,\r
+                    &Handles\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      NumHandles = 0;\r
+      Handles    = NULL;\r
     }\r
+    for (Index = 0; Index < NumHandles; Index++) {\r
+      //\r
+      // Open Unicode Collation Protocol\r
+      //\r
+      Status = gBS->OpenProtocol (\r
+                      Handles[Index],\r
+                      &gEfiUnicodeCollation2ProtocolGuid,\r
+                      (VOID **) &Uc,\r
+                      gImageHandle,\r
+                      NULL,\r
+                      EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        continue;\r
+      }\r
+\r
+      //\r
+      // Find the best matching matching language from the supported languages\r
+      // of Unicode Collation2 protocol.\r
+      //\r
+      BestLanguage = GetBestLanguage (\r
+                       Uc->SupportedLanguages,\r
+                       FALSE,\r
+                       PlatformLang,\r
+                       NULL\r
+                       );\r
+      if (BestLanguage != NULL) {\r
+        FreePool (BestLanguage);\r
+        gUnicodeCollation = Uc;\r
+        break;\r
+      }\r
+    }\r
+    if (Handles != NULL) {\r
+      FreePool (Handles);\r
+    }\r
+    FreePool (PlatformLang);\r
   }\r
-  return (EFI_SUCCESS);\r
+\r
+  return (gUnicodeCollation == NULL) ? EFI_UNSUPPORTED : EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -91,11 +162,9 @@ ShellCommandLibConstructor (
   mProfileListSize  = 0;\r
   mProfileList      = NULL;\r
 \r
-  if (gUnicodeCollation == NULL) {\r
-    Status = gBS->LocateProtocol(&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&gUnicodeCollation);\r
-    if (EFI_ERROR(Status)) {\r
-      return (EFI_DEVICE_ERROR);\r
-    }\r
+  Status = CommandInit ();\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
   }\r
 \r
   return (RETURN_SUCCESS);\r
@@ -107,7 +176,6 @@ ShellCommandLibConstructor (
   @param[in] List     The list to free.\r
 **/\r
 VOID\r
-EFIAPI\r
 FreeFileHandleList (\r
   IN BUFFER_LIST *List\r
   )\r
@@ -209,13 +277,13 @@ ShellCommandLibDestructor (
   }\r
 \r
   gUnicodeCollation            = NULL;\r
-  gShellCurDir                 = NULL;\r
+  gShellCurMapping             = NULL;\r
 \r
   return (RETURN_SUCCESS);\r
 }\r
 \r
 /**\r
-  Find a dynamic command protocol instance given a command name string\r
+  Find a dynamic command protocol instance given a command name string.\r
 \r
   @param CommandString  the command name string\r
 \r
@@ -223,7 +291,6 @@ ShellCommandLibDestructor (
   @retval NULL          no dynamic command protocol instance found for name\r
 **/\r
 CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *\r
-EFIAPI\r
 ShellCommandFindDynamicCommand (\r
   IN CONST CHAR16 *CommandString\r
   )\r
@@ -238,7 +305,7 @@ ShellCommandFindDynamicCommand (
     //\r
     // not found or out of resources\r
     //\r
-    return NULL; \r
+    return NULL;\r
   }\r
 \r
   for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) {\r
@@ -255,7 +322,7 @@ ShellCommandFindDynamicCommand (
     if (gUnicodeCollation->StriColl(\r
           gUnicodeCollation,\r
           (CHAR16*)CommandString,\r
-          (CHAR16*)DynamicCommand->CommandName) == 0 \r
+          (CHAR16*)DynamicCommand->CommandName) == 0\r
           ){\r
         FreePool(CommandHandleList);\r
         return (DynamicCommand);\r
@@ -272,12 +339,11 @@ ShellCommandFindDynamicCommand (
   @param[in] CommandString        The command string to check for on the list.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 ShellCommandDynamicCommandExists (\r
   IN CONST CHAR16 *CommandString\r
   )\r
 {\r
-  return (ShellCommandFindDynamicCommand(CommandString) != NULL);\r
+  return (BOOLEAN) ((ShellCommandFindDynamicCommand(CommandString) != NULL));\r
 }\r
 \r
 /**\r
@@ -286,7 +352,6 @@ ShellCommandDynamicCommandExists (
   @param[in] CommandString        The command string to check for on the list.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 ShellCommandIsCommandOnInternalList(\r
   IN CONST  CHAR16 *CommandString\r
   )\r
@@ -344,7 +409,6 @@ ShellCommandIsCommandOnList(
   @return       String of help text. Caller required to free.\r
 **/\r
 CHAR16*\r
-EFIAPI\r
 ShellCommandGetDynamicCommandHelp(\r
   IN CONST  CHAR16                      *CommandString\r
   )\r
@@ -359,7 +423,7 @@ ShellCommandGetDynamicCommandHelp(
   //\r
   // TODO: how to get proper language?\r
   //\r
-  return DynamicCommand->GetHelp(DynamicCommand, "en"); \r
+  return DynamicCommand->GetHelp(DynamicCommand, "en");\r
 }\r
 \r
 /**\r
@@ -371,7 +435,6 @@ ShellCommandGetDynamicCommandHelp(
   @return       String of help text. Caller reuiqred to free.\r
 **/\r
 CHAR16*\r
-EFIAPI\r
 ShellCommandGetInternalCommandHelp(\r
   IN CONST  CHAR16                      *CommandString\r
   )\r
@@ -525,14 +588,14 @@ ShellCommandRegisterCommandName (
   // allocate memory for new struct\r
   //\r
   Node = AllocateZeroPool(sizeof(SHELL_COMMAND_INTERNAL_LIST_ENTRY));\r
-  ASSERT(Node != NULL);\r
-  Node->CommandString = AllocateZeroPool(StrSize(CommandString));\r
-  ASSERT(Node->CommandString != NULL);\r
-\r
-  //\r
-  // populate the new struct\r
-  //\r
-  StrCpy(Node->CommandString, CommandString);\r
+  if (Node == NULL) {\r
+    return RETURN_OUT_OF_RESOURCES;\r
+  }\r
+  Node->CommandString = AllocateCopyPool(StrSize(CommandString), CommandString);\r
+  if (Node->CommandString == NULL) {\r
+    FreePool (Node);\r
+    return RETURN_OUT_OF_RESOURCES;\r
+  }\r
 \r
   Node->GetManFileName  = GetManFileName;\r
   Node->CommandHandler  = CommandHandler;\r
@@ -777,6 +840,9 @@ ShellCommandRegisterAlias (
   )\r
 {\r
   ALIAS_LIST *Node;\r
+  ALIAS_LIST *CommandAlias;\r
+  ALIAS_LIST *PrevCommandAlias;\r
+  INTN       LexicalMatchValue;\r
 \r
   //\r
   // Asserts for NULL\r
@@ -788,22 +854,52 @@ ShellCommandRegisterAlias (
   // allocate memory for new struct\r
   //\r
   Node = AllocateZeroPool(sizeof(ALIAS_LIST));\r
-  ASSERT(Node != NULL);\r
-  Node->CommandString = AllocateZeroPool(StrSize(Command));\r
-  Node->Alias = AllocateZeroPool(StrSize(Alias));\r
-  ASSERT(Node->CommandString != NULL);\r
-  ASSERT(Node->Alias != NULL);\r
+  if (Node == NULL) {\r
+    return RETURN_OUT_OF_RESOURCES;\r
+  }\r
+  Node->CommandString = AllocateCopyPool(StrSize(Command), Command);\r
+  if (Node->CommandString == NULL) {\r
+    FreePool (Node);\r
+    return RETURN_OUT_OF_RESOURCES;\r
+  }\r
+  Node->Alias = AllocateCopyPool(StrSize(Alias), Alias);\r
+  if (Node->Alias == NULL) {\r
+    FreePool (Node->CommandString);\r
+    FreePool (Node);\r
+    return RETURN_OUT_OF_RESOURCES;\r
+  }\r
 \r
-  //\r
-  // populate the new struct\r
-  //\r
-  StrCpy(Node->CommandString, Command);\r
-  StrCpy(Node->Alias        , Alias );\r
+  InsertHeadList (&mAliasList.Link, &Node->Link);\r
 \r
   //\r
-  // add the new struct to the list\r
+  // Move a new pre-defined registered alias to its sorted ordered location in the list\r
   //\r
-  InsertTailList (&mAliasList.Link, &Node->Link);\r
+  for ( CommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link),\r
+         PrevCommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link)\r
+       ; !IsNull (&mAliasList.Link, &CommandAlias->Link)\r
+       ; CommandAlias = (ALIAS_LIST *) GetNextNode (&mAliasList.Link, &CommandAlias->Link) ) {\r
+    //\r
+    // Get Lexical comparison value between PrevCommandAlias and CommandAlias List Entry\r
+    //\r
+    LexicalMatchValue = gUnicodeCollation->StriColl (\r
+                                             gUnicodeCollation,\r
+                                             PrevCommandAlias->Alias,\r
+                                             CommandAlias->Alias\r
+                                             );\r
+\r
+    //\r
+    // Swap PrevCommandAlias and CommandAlias list entry if PrevCommandAlias list entry\r
+    // is alphabetically greater than CommandAlias list entry\r
+    //\r
+    if (LexicalMatchValue > 0) {\r
+      CommandAlias = (ALIAS_LIST *) SwapListEntries (&PrevCommandAlias->Link, &CommandAlias->Link);\r
+    } else if (LexicalMatchValue < 0) {\r
+      //\r
+      // PrevCommandAlias entry is lexically lower than CommandAlias entry\r
+      //\r
+      break;\r
+    }\r
+  }\r
 \r
   return (RETURN_SUCCESS);\r
 }\r
@@ -873,7 +969,7 @@ ShellCommandIsOnAliasList(
 }\r
 \r
 /**\r
-  Function to determine current state of ECHO.  Echo determins if lines from scripts\r
+  Function to determine current state of ECHO.  Echo determines if lines from scripts\r
   and ECHO commands are enabled.\r
 \r
   @retval TRUE    Echo is currently enabled\r
@@ -889,7 +985,7 @@ ShellCommandGetEchoState(
 }\r
 \r
 /**\r
-  Function to set current state of ECHO.  Echo determins if lines from scripts\r
+  Function to set current state of ECHO.  Echo determines if lines from scripts\r
   and ECHO commands are enabled.\r
 \r
   If State is TRUE, Echo will be enabled.\r
@@ -1146,12 +1242,11 @@ ShellCommandAddMapItemAndUpdatePath(
     Status = EFI_OUT_OF_RESOURCES;\r
   } else {\r
     MapListNode->Flags = Flags;\r
-    MapListNode->MapName = AllocateZeroPool(StrSize(Name));\r
+    MapListNode->MapName = AllocateCopyPool(StrSize(Name), Name);\r
     MapListNode->DevicePath = DuplicateDevicePath(DevicePath);\r
     if ((MapListNode->MapName == NULL) || (MapListNode->DevicePath == NULL)){\r
       Status = EFI_OUT_OF_RESOURCES;\r
     } else {\r
-      StrCpy(MapListNode->MapName, Name);\r
       InsertTailList(&gShellMapList.Link, &MapListNode->Link);\r
     }\r
   }\r
@@ -1174,10 +1269,8 @@ ShellCommandAddMapItemAndUpdatePath(
     ASSERT((NewPath == NULL && NewPathSize == 0) || (NewPath != NULL));\r
     if (OriginalPath != NULL) {\r
       StrnCatGrow(&NewPath, &NewPathSize, OriginalPath, 0);\r
-    } else {\r
-      StrnCatGrow(&NewPath, &NewPathSize, L".\\", 0);\r
+      StrnCatGrow(&NewPath, &NewPathSize, L";", 0);\r
     }\r
-    StrnCatGrow(&NewPath, &NewPathSize, L";", 0);\r
     StrnCatGrow(&NewPath, &NewPathSize, Name, 0);\r
     StrnCatGrow(&NewPath, &NewPathSize, L"\\efi\\tools\\;", 0);\r
     StrnCatGrow(&NewPath, &NewPathSize, Name, 0);\r
@@ -1223,7 +1316,14 @@ ShellCommandCreateInitialMappingsAndPaths(
   CHAR16                    *NewConsistName;\r
   EFI_DEVICE_PATH_PROTOCOL  **ConsistMappingTable;\r
   SHELL_MAP_LIST            *MapListNode;\r
-\r
+  CONST CHAR16              *CurDir;\r
+  CHAR16                    *SplitCurDir;\r
+  CHAR16                    *MapName;\r
+  SHELL_MAP_LIST            *MapListItem;\r
+\r
+  SplitCurDir = NULL;\r
+  MapName     = NULL;\r
+  MapListItem = NULL;\r
   HandleList  = NULL;\r
 \r
   //\r
@@ -1243,6 +1343,9 @@ ShellCommandCreateInitialMappingsAndPaths(
         ; MapListNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)\r
        ){\r
           RemoveEntryList(&MapListNode->Link);\r
+          SHELL_FREE_NON_NULL(MapListNode->DevicePath);\r
+          SHELL_FREE_NON_NULL(MapListNode->MapName);\r
+          SHELL_FREE_NON_NULL(MapListNode->CurrentDirectoryPath);\r
           FreePool(MapListNode);\r
     } // for loop\r
   }\r
@@ -1261,7 +1364,10 @@ ShellCommandCreateInitialMappingsAndPaths(
     // Get all Device Paths\r
     //\r
     DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);\r
-    ASSERT(DevicePathList != NULL);\r
+    if (DevicePathList == NULL) {\r
+      SHELL_FREE_NON_NULL (HandleList);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
 \r
     for (Count = 0 ; HandleList[Count] != NULL ; Count++) {\r
       DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);\r
@@ -1303,6 +1409,33 @@ ShellCommandCreateInitialMappingsAndPaths(
     SHELL_FREE_NON_NULL(DevicePathList);\r
 \r
     HandleList = NULL;\r
+\r
+    //\r
+    //gShellCurMapping point to node of current file system in the gShellMapList. When reset all mappings,\r
+    //all nodes in the gShellMapList will be free. Then gShellCurMapping will be a dangling pointer, So,\r
+    //after created new mappings, we should reset the gShellCurMapping pointer back to node of current file system.\r
+    //\r
+    if (gShellCurMapping != NULL) {\r
+      gShellCurMapping = NULL;\r
+      CurDir = gEfiShellProtocol->GetEnv(L"cwd");\r
+      if (CurDir != NULL) {\r
+        MapName = AllocateCopyPool (StrSize(CurDir), CurDir);\r
+        if (MapName == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+        SplitCurDir = StrStr (MapName, L":");\r
+        if (SplitCurDir == NULL) {\r
+          SHELL_FREE_NON_NULL (MapName);\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+        *(SplitCurDir + 1) = CHAR_NULL;\r
+        MapListItem = ShellCommandFindMapItem (MapName);\r
+        if (MapListItem != NULL) {\r
+          gShellCurMapping = MapListItem;\r
+        }\r
+        SHELL_FREE_NON_NULL (MapName);\r
+      }\r
+    }\r
   } else {\r
     Count = (UINTN)-1;\r
   }\r
@@ -1318,7 +1451,10 @@ ShellCommandCreateInitialMappingsAndPaths(
     // Get all Device Paths\r
     //\r
     DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);\r
-    ASSERT(DevicePathList != NULL);\r
+    if (DevicePathList == NULL) {\r
+      SHELL_FREE_NON_NULL (HandleList);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
 \r
     for (Count = 0 ; HandleList[Count] != NULL ; Count++) {\r
       DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);\r
@@ -1604,7 +1740,6 @@ ShellFileHandleEof(
 \r
   gEfiShellProtocol->GetFilePosition(Handle, &Pos);\r
   Info = gEfiShellProtocol->GetFileInfo (Handle);\r
-  ASSERT(Info != NULL);\r
   gEfiShellProtocol->SetFilePosition(Handle, Pos);\r
 \r
   if (Info == NULL) {\r
@@ -1653,3 +1788,112 @@ FreeBufferList (
   }\r
 }\r
 \r
+/**\r
+  Dump some hexadecimal data to the screen.\r
+\r
+  @param[in] Indent     How many spaces to indent the output.\r
+  @param[in] Offset     The offset of the printing.\r
+  @param[in] DataSize   The size in bytes of UserData.\r
+  @param[in] UserData   The data to print out.\r
+**/\r
+VOID\r
+EFIAPI\r
+DumpHex (\r
+  IN UINTN        Indent,\r
+  IN UINTN        Offset,\r
+  IN UINTN        DataSize,\r
+  IN VOID         *UserData\r
+  )\r
+{\r
+  UINT8 *Data;\r
+\r
+  CHAR8 Val[50];\r
+\r
+  CHAR8 Str[20];\r
+\r
+  UINT8 TempByte;\r
+  UINTN Size;\r
+  UINTN Index;\r
+\r
+  Data = UserData;\r
+  while (DataSize != 0) {\r
+    Size = 16;\r
+    if (Size > DataSize) {\r
+      Size = DataSize;\r
+    }\r
+\r
+    for (Index = 0; Index < Size; Index += 1) {\r
+      TempByte            = Data[Index];\r
+      Val[Index * 3 + 0]  = Hex[TempByte >> 4];\r
+      Val[Index * 3 + 1]  = Hex[TempByte & 0xF];\r
+      Val[Index * 3 + 2]  = (CHAR8) ((Index == 7) ? '-' : ' ');\r
+      Str[Index]          = (CHAR8) ((TempByte < ' ' || TempByte > '~') ? '.' : TempByte);\r
+    }\r
+\r
+    Val[Index * 3]  = 0;\r
+    Str[Index]      = 0;\r
+    ShellPrintEx(-1, -1, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);\r
+\r
+    Data += Size;\r
+    Offset += Size;\r
+    DataSize -= Size;\r
+  }\r
+}\r
+\r
+/**\r
+  Dump HEX data into buffer.\r
+\r
+  @param[in] Buffer     HEX data to be dumped in Buffer.\r
+  @param[in] Indent     How many spaces to indent the output.\r
+  @param[in] Offset     The offset of the printing.\r
+  @param[in] DataSize   The size in bytes of UserData.\r
+  @param[in] UserData   The data to print out.\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+CatSDumpHex (\r
+  IN CHAR16  *Buffer,\r
+  IN UINTN   Indent,\r
+  IN UINTN   Offset,\r
+  IN UINTN   DataSize,\r
+  IN VOID    *UserData\r
+  )\r
+{\r
+  UINT8   *Data;\r
+  UINT8   TempByte;\r
+  UINTN   Size;\r
+  UINTN   Index;\r
+  CHAR8   Val[50];\r
+  CHAR8   Str[20];\r
+  CHAR16  *RetVal;\r
+  CHAR16  *TempRetVal;\r
+\r
+  Data = UserData;\r
+  RetVal = Buffer;\r
+  while (DataSize != 0) {\r
+    Size = 16;\r
+    if (Size > DataSize) {\r
+      Size = DataSize;\r
+    }\r
+\r
+    for (Index = 0; Index < Size; Index += 1) {\r
+      TempByte            = Data[Index];\r
+      Val[Index * 3 + 0]  = Hex[TempByte >> 4];\r
+      Val[Index * 3 + 1]  = Hex[TempByte & 0xF];\r
+      Val[Index * 3 + 2]  = (CHAR8) ((Index == 7) ? '-' : ' ');\r
+      Str[Index]          = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);\r
+    }\r
+\r
+    Val[Index * 3]  = 0;\r
+    Str[Index]      = 0;\r
+    TempRetVal = CatSPrint (RetVal, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);\r
+    SHELL_FREE_NON_NULL (RetVal);\r
+    RetVal = TempRetVal;\r
+\r
+    Data += Size;\r
+    Offset += Size;\r
+    DataSize -= Size;\r
+  }\r
+\r
+  return RetVal;\r
+}\r