]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmbeddedPkg/Ebl/Command.c
Update EBL to have an optional width specifier on commands. So hexdump.4 means use...
[mirror_edk2.git] / EmbeddedPkg / Ebl / Command.c
index 7899a0f442c53816a956bb408b58d7e41a9fb7bb..3efe6ee671e6e6e1376055d374eb9c59b165024e 100644 (file)
@@ -186,8 +186,16 @@ EblGetCommand (
   UINTN               BestMatchCount;\r
   UINTN               Length;\r
   EBL_COMMAND_TABLE   *Match;\r
+  CHAR8               *Str;\r
 \r
   Length = AsciiStrLen (CommandName);\r
+  Str = AsciiStrStr (CommandName, ".");\r
+  if (Str != NULL) {\r
+    // If the command includes a trailing . command extension skip it for the match.\r
+    // Example: hexdump.4\r
+    Length = (UINTN)(Str - CommandName); \r
+  }\r
+  \r
   for (Index = 0, BestMatchCount = 0, Match = NULL; Index < mCmdTableNextFreeIndex; Index++) {\r
     if (AsciiStriCmp (mCmdTable[Index]->Name,  CommandName) == 0) {\r
       // match a command exactly\r
@@ -282,13 +290,13 @@ EblExitCmd (
   IN CHAR8  **Argv\r
   )\r
 {\r
-  EFI_STATUS              Status;
-  UINTN                   MemoryMapSize;
-  EFI_MEMORY_DESCRIPTOR   *MemoryMap;
-  UINTN                   MapKey;
-  UINTN                   DescriptorSize;
-  UINTN                   DescriptorVersion;
-  UINTN                   Pages;
+  EFI_STATUS              Status;\r
+  UINTN                   MemoryMapSize;\r
+  EFI_MEMORY_DESCRIPTOR   *MemoryMap;\r
+  UINTN                   MapKey;\r
+  UINTN                   DescriptorSize;\r
+  UINT32                  DescriptorVersion;\r
+  UINTN                   Pages;\r
 \r
   if (Argc > 1) { \r
     if (AsciiStriCmp (Argv[1], "efi") != 0) {\r
@@ -298,42 +306,42 @@ EblExitCmd (
     return EFI_ABORTED;\r
   }\r
   \r
-  MemoryMap = NULL;
-  MemoryMapSize = 0;
-  do {
-    Status = gBS->GetMemoryMap (
-                    &MemoryMapSize,
-                    MemoryMap,
-                    &MapKey,
-                    &DescriptorSize,
-                    &DescriptorVersion
-                    );
-    if (Status == EFI_BUFFER_TOO_SMALL) {
-
-      Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
-      MemoryMap = AllocatePages (Pages);
-    
-      //
-      // Get System MemoryMap
-      //
-      Status = gBS->GetMemoryMap (
-                      &MemoryMapSize,
-                      MemoryMap,
-                      &MapKey,
-                      &DescriptorSize,
-                      &DescriptorVersion
-                      );
-      // Don't do anything between the GetMemoryMap() and ExitBootServices()
-      if (!EFI_ERROR (Status)) {
-        Status = gBS->ExitBootServices (gImageHandle, MapKey);
-        if (EFI_ERROR (Status)) {
-          FreePages (MemoryMap, Pages);
-          MemoryMap = NULL;
-          MemoryMapSize = 0;
-        }
-      }
-    }
-  } while (EFI_ERROR (Status));
+  MemoryMap = NULL;\r
+  MemoryMapSize = 0;\r
+  do {\r
+    Status = gBS->GetMemoryMap (\r
+                    &MemoryMapSize,\r
+                    MemoryMap,\r
+                    &MapKey,\r
+                    &DescriptorSize,\r
+                    &DescriptorVersion\r
+                    );\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+      Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;\r
+      MemoryMap = AllocatePages (Pages);\r
+    \r
+      //\r
+      // Get System MemoryMap\r
+      //\r
+      Status = gBS->GetMemoryMap (\r
+                      &MemoryMapSize,\r
+                      MemoryMap,\r
+                      &MapKey,\r
+                      &DescriptorSize,\r
+                      &DescriptorVersion\r
+                      );\r
+      // Don't do anything between the GetMemoryMap() and ExitBootServices()\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = gBS->ExitBootServices (gImageHandle, MapKey);\r
+        if (EFI_ERROR (Status)) {\r
+          FreePages (MemoryMap, Pages);\r
+          MemoryMap = NULL;\r
+          MemoryMapSize = 0;\r
+        }\r
+      }\r
+    }\r
+  } while (EFI_ERROR (Status));\r
 \r
   //\r
   // At this point it is very dangerous to do things EFI as most of EFI is now gone.\r
@@ -525,12 +533,9 @@ ConvertToTextLine (
   IN CHAR8  Character\r
   )\r
 {\r
-  if (Character < ' ' || Character > '~')\r
-  {\r
+  if (Character < ' ' || Character > '~') {\r
     return '.';\r
-  }\r
-  else\r
-  {\r
+  } else {\r
     return Character;\r
   }\r
 }\r
@@ -543,15 +548,15 @@ GetBytes (
 {\r
   UINTN Result = 0;\r
 \r
-  if (Bytes >= 1)\r
+  if (Bytes >= 1) {\r
     Result = *Address++;\r
-    \r
-  if (Bytes >= 2)\r
+  }\r
+  if (Bytes >= 2) {\r
     Result = (Result << 8) + *Address++;\r
-    \r
-  if (Bytes >= 3)\r
+  }  \r
+  if (Bytes >= 3) {\r
     Result = (Result << 8) + *Address++;\r
-\r
+  }\r
   return Result;\r
 }\r
 \r
@@ -574,26 +579,20 @@ OutputData (
   CHAR8 Blanks[80];\r
 \r
   AsciiStrCpy (Blanks, mBlanks);\r
-  for (EndAddress = Address + Length; Address < EndAddress; Offset += Line)\r
-  {\r
+  for (EndAddress = Address + Length; Address < EndAddress; Offset += Line) {\r
     AsciiPrint ("%08x: ", Offset);\r
-    for (Line = 0; (Line < 0x10) && (Address < EndAddress);)\r
-    {\r
+    for (Line = 0; (Line < 0x10) && (Address < EndAddress);) {\r
       Bytes = EndAddress - Address;\r
             \r
-      switch (Width)\r
-      {\r
+      switch (Width) {\r
         case 4:\r
-          if (Bytes >= 4)\r
-          {\r
+          if (Bytes >= 4) {\r
             AsciiPrint ("%08x ", *((UINT32 *)Address));\r
             TextLine[Line++] = ConvertToTextLine(*Address++);\r
             TextLine[Line++] = ConvertToTextLine(*Address++);\r
             TextLine[Line++] = ConvertToTextLine(*Address++);\r
             TextLine[Line++] = ConvertToTextLine(*Address++);\r
-          }\r
-          else\r
-          {\r
+          } else {\r
             AsciiPrint ("%08x ", GetBytes(Address, Bytes));\r
             Address += Bytes;\r
             Line    += Bytes;\r
@@ -601,14 +600,11 @@ OutputData (
           break;\r
 \r
         case 2:\r
-          if (Bytes >= 2)\r
-          {\r
+          if (Bytes >= 2) {\r
             AsciiPrint ("%04x ", *((UINT16 *)Address));\r
             TextLine[Line++] = ConvertToTextLine(*Address++);\r
             TextLine[Line++] = ConvertToTextLine(*Address++);\r
-          }\r
-          else\r
-          {\r
+          } else {\r
             AsciiPrint ("%04x ", GetBytes(Address, Bytes));\r
             Address += Bytes;\r
             Line    += Bytes;\r
@@ -627,10 +623,8 @@ OutputData (
     }\r
 \r
     // Pad spaces\r
-    if (Line < 0x10)\r
-    {\r
-      switch (Width)\r
-      {\r
+    if (Line < 0x10) {\r
+      switch (Width) {\r
         case 4:\r
           Spaces = 9 * ((0x10 - Line)/4);\r
           break;\r
@@ -652,22 +646,72 @@ OutputData (
     TextLine[Line] = 0;\r
     AsciiPrint ("|%a|\n", TextLine);\r
 \r
-    if (EblAnyKeyToContinueQtoQuit(&CurrentRow, FALSE))\r
-    {\r
+    if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {\r
       return EFI_END_OF_FILE;\r
     }\r
   }\r
 \r
-  if (Length % Width != 0)\r
-  {\r
+  if (Length % Width != 0) {\r
     AsciiPrint ("%08x\n", Offset);\r
   }\r
   \r
   return EFI_SUCCESS;\r
 }\r
 \r
+\r
+/**\r
+  See if command contains .# where # is a number. Return # as the Width\r
+  or 1 as the default Width for commands. \r
+  \r
+  Example hexdump.4 returns a width of 4.\r
+\r
+  @param  Argv   Argv[0] is the comamnd name\r
+\r
+  @return Width of command\r
+\r
+**/\r
+UINTN\r
+WidthFromCommandName (\r
+  IN CHAR8  *Argv,\r
+  IN UINTN  Default\r
+  )\r
+{\r
+  CHAR8         *Str;\r
+  UINTN         Width;\r
+  \r
+  //Hexdump.2 HexDump.4 mean use a different width\r
+  Str = AsciiStrStr (Argv, ".");\r
+  if (Str != NULL) {\r
+    Width = AsciiStrDecimalToUintn (Str + 1);\r
+    if (Width == 0) {\r
+      Width = Default;\r
+    }\r
+  } else {\r
+    // Default answer\r
+    return Default;\r
+  }\r
+\r
+  return Width;\r
+}\r
+\r
 #define HEXDUMP_CHUNK 1024\r
 \r
+/**\r
+  Toggle page break global. This turns on and off prompting to Quit or hit any\r
+  key to continue when a command is about to scroll the screen with its output\r
+\r
+  Argv[0] - "hexdump"[.#]  # is optional 1,2, or 4 for width  \r
+  Argv[1] - Device or File to dump. \r
+  Argv[2] - Optional offset to start dumping\r
+  Argv[3] - Optional number of bytes to dump\r
+\r
+  @param  Argc   Number of command arguments in Argv\r
+  @param  Argv   Array of strings that represent the parsed command line. \r
+                 Argv[0] is the comamnd name\r
+\r
+  @return EFI_SUCCESS\r
+\r
+**/\r
 EFI_STATUS\r
 EblHexdumpCmd (\r
   IN UINTN  Argc,\r
@@ -677,49 +721,52 @@ EblHexdumpCmd (
   EFI_OPEN_FILE *File;\r
   VOID          *Location;\r
   UINTN         Size;\r
-  UINTN         Width = 1;\r
+  UINTN         Width;\r
   UINTN         Offset = 0;\r
   EFI_STATUS    Status;\r
   UINTN         Chunk = HEXDUMP_CHUNK;\r
 \r
-  if ((Argc < 2) || (Argc > 3))\r
-  {\r
+  if ((Argc < 2) || (Argc > 4)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   \r
-  if (Argc == 3)\r
-  {\r
-      Width = AsciiStrDecimalToUintn(Argv[2]);\r
-  }\r
-  \r
-  if ((Width != 1) && (Width != 2) && (Width != 4))\r
-  {\r
+  Width = WidthFromCommandName (Argv[0], 1);\r
+  if ((Width != 1) && (Width != 2) && (Width != 4)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  File = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);\r
-  if (File == NULL)\r
-  {\r
+  File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);\r
+  if (File == NULL) {\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  Location = AllocatePool(Chunk);\r
-  Size     = EfiTell(File, NULL);\r
+  Location = AllocatePool (Chunk);\r
+  Size     = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : EfiTell (File, NULL);\r
 \r
-  for (Offset = 0; Offset + HEXDUMP_CHUNK <= Size; Offset += Chunk)\r
-  {\r
+  Offset = 0;\r
+  if (Argc > 2) {\r
+    Offset = AsciiStrHexToUintn (Argv[2]);\r
+    if (Offset > 0) {\r
+      // Make sure size includes the part of the file we have skipped\r
+      Size += Offset;\r
+    }\r
+  } \r
+\r
+  Status = EfiSeek (File, Offset, EfiSeekStart);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+  \r
+  for (; Offset + HEXDUMP_CHUNK <= Size; Offset += Chunk) {\r
     Chunk = HEXDUMP_CHUNK;\r
-    \r
-    Status = EfiRead(File, Location, &Chunk);\r
-    if (EFI_ERROR(Status))\r
-    {\r
+    Status = EfiRead (File, Location, &Chunk);\r
+    if (EFI_ERROR(Status)) {\r
       AsciiPrint ("Error reading file content\n");\r
       goto Exit;\r
     }\r
 \r
-    Status = OutputData(Location, Chunk, Width, File->BaseOffset + Offset);\r
-    if (EFI_ERROR(Status))\r
-    {\r
+    Status = OutputData (Location, Chunk, Width, File->BaseOffset + Offset);\r
+    if (EFI_ERROR(Status)) {\r
       if (Status == EFI_END_OF_FILE) {\r
         Status = EFI_SUCCESS;\r
       }\r
@@ -728,19 +775,16 @@ EblHexdumpCmd (
   }\r
   \r
   // Any left over?\r
-  if (Offset < Size)\r
-  {\r
+  if (Offset < Size) {\r
     Chunk = Size - Offset;\r
-    Status = EfiRead(File, Location, &Chunk);\r
-    if (EFI_ERROR(Status))\r
-    {\r
+    Status = EfiRead (File, Location, &Chunk);\r
+    if (EFI_ERROR(Status)) {\r
       AsciiPrint ("Error reading file content\n");\r
       goto Exit;\r
     }\r
 \r
-    Status = OutputData(Location, Chunk, Width, File->BaseOffset + Offset);\r
-    if (EFI_ERROR(Status))\r
-    {\r
+    Status = OutputData (Location, Chunk, Width, File->BaseOffset + Offset);\r
+    if (EFI_ERROR(Status)) {\r
       if (Status == EFI_END_OF_FILE) {\r
         Status = EFI_SUCCESS;\r
       }\r
@@ -749,141 +793,13 @@ EblHexdumpCmd (
   }\r
 \r
 Exit:\r
-  EfiClose(File);\r
+  EfiClose (File);\r
 \r
-  FreePool(Location);\r
+  FreePool (Location);\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-#define USE_DISKIO 1\r
-\r
-EFI_STATUS\r
-EblDiskIoCmd (\r
-  IN UINTN Argc,\r
-  IN CHAR8 **Argv\r
-  )\r
-{\r
-  EFI_STATUS Status;\r
-  UINTN Offset;\r
-  UINT8 *EndOffset;\r
-  UINTN Length;\r
-  UINTN Line;\r
-  UINT8 *Buffer;\r
-  UINT8 *BufferOffset;\r
-  CHAR8 TextLine[0x11];\r
-#if USE_DISKIO\r
-  EFI_DISK_IO_PROTOCOL  *DiskIo;\r
-#else\r
-  EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
-  UINTN                 Lba;\r
-#endif  \r
-\r
-  if (AsciiStrCmp(Argv[1], "r") == 0)\r
-  {  \r
-    Offset = AsciiStrHexToUintn(Argv[2]);\r
-    Length = AsciiStrHexToUintn(Argv[3]);\r
-\r
-#if USE_DISKIO\r
-    Status = gBS->LocateProtocol(&gEfiDiskIoProtocolGuid, NULL, (VOID **)&DiskIo);\r
-    if (EFI_ERROR(Status))\r
-    {\r
-      AsciiPrint("Did not locate DiskIO\n");\r
-      return Status;\r
-    }\r
-\r
-    Buffer = AllocatePool(Length);\r
-    BufferOffset = Buffer;\r
-    \r
-    Status = DiskIo->ReadDisk(DiskIo, SIGNATURE_32('f','l','s','h'), Offset, Length, Buffer);\r
-    if (EFI_ERROR(Status))\r
-    {\r
-      AsciiPrint("DiskIO read failed\n");\r
-      gBS->FreePool(Buffer);\r
-      return Status;\r
-    }    \r
-#else\r
-    Status = gBS->LocateProtocol(&gEfiBlockIoProtocolGuid, NULL, (VOID **)&BlockIo);\r
-    if (EFI_ERROR(Status))\r
-    {\r
-      AsciiPrint("Did not locate BlockIo\n");\r
-      return Status;\r
-    }\r
-    \r
-    Length = BlockIo->Media->BlockSize;\r
-    Buffer = AllocatePool(Length);\r
-    BufferOffset = Buffer;\r
-    Lba = Offset/BlockIo->Media->BlockSize;\r
-    \r
-    Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, Lba, Length, Buffer);\r
-    if (EFI_ERROR(Status))\r
-    {\r
-      AsciiPrint("BlockIo read failed\n");\r
-      gBS->FreePool(Buffer);\r
-      return Status;\r
-    }\r
-    \r
-    // Whack offset to what we actually read from\r
-    Offset = Lba * BlockIo->Media->BlockSize;\r
-    \r
-    Length = 0x100;\r
-#endif\r
-\r
-    for (EndOffset = BufferOffset + Length; BufferOffset < EndOffset; Offset += 0x10)\r
-    {\r
-      AsciiPrint ("%08x: ", Offset);\r
-      \r
-      for (Line = 0; Line < 0x10; Line++)\r
-      {\r
-        AsciiPrint ("%02x ", *BufferOffset);\r
-\r
-        if (*BufferOffset < ' ' || *BufferOffset > '~')\r
-          TextLine[Line] = '.';\r
-        else\r
-          TextLine[Line] = *BufferOffset;\r
-          \r
-        BufferOffset++;\r
-      }\r
-\r
-      TextLine[Line] = '\0';\r
-      AsciiPrint ("|%a|\n", TextLine);\r
-    }\r
-    \r
-    gBS->FreePool(Buffer);\r
-\r
-    return EFI_SUCCESS;\r
-  }\r
-  else if (AsciiStrCmp(Argv[1], "w") == 0)\r
-  {\r
-    Offset = AsciiStrHexToUintn(Argv[2]);\r
-    Length = AsciiStrHexToUintn(Argv[3]);\r
-    Buffer = (UINT8 *)AsciiStrHexToUintn(Argv[4]);\r
-    \r
-#if USE_DISKIO\r
-    Status = gBS->LocateProtocol(&gEfiDiskIoProtocolGuid, NULL, (VOID **)&DiskIo);\r
-    if (EFI_ERROR(Status))\r
-    {\r
-      AsciiPrint("Did not locate DiskIO\n");\r
-      return Status;\r
-    }\r
-\r
-    Status = DiskIo->WriteDisk(DiskIo, SIGNATURE_32('f','l','s','h'), Offset, Length, Buffer);\r
-    if (EFI_ERROR(Status))\r
-    {\r
-      AsciiPrint("DiskIO write failed\n");\r
-      return Status;\r
-    }\r
-\r
-#else\r
-#endif\r
-\r
-    return EFI_SUCCESS;\r
-  }\r
-  else\r
-  {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-}\r
 \r
 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdTemplate[] =\r
 {\r
@@ -931,16 +847,10 @@ GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdTemplate[] =
   },\r
   {\r
     "hexdump",\r
-    " filename ; dump a file as hex bytes",\r
+    "[.{1|2|4}] filename [Offset] [Size]; dump a file as hex bytes at a given width",\r
     NULL,\r
     EblHexdumpCmd\r
-  },\r
-  {\r
-    "diskio",\r
-    " [r|w] offset [length [dataptr]]; do a DiskIO read or write ",\r
-    NULL,\r
-    EblDiskIoCmd\r
-  }  \r
+  }\r
 };\r
 \r
 \r