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
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
{\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
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
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
}\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
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
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
}\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
}\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
},\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