From 2ef2b01e07c02db339f34004445734a2dbdd80e1 Mon Sep 17 00:00:00 2001 From: AJFISH Date: Sun, 6 Dec 2009 01:57:05 +0000 Subject: Adding support for BeagleBoard. ArmPkg - Supoprt for ARM specific things that can change as the architecture changes. Plus semihosting JTAG drivers. EmbeddedPkg - Generic support for an embeddded platform. Including a light weight command line shell. BeagleBoardPkg - Platform specifics for BeagleBoard. SD Card works, but USB has issues. Looks like a bug in the open source USB stack (Our internal stack works fine). git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9518 6f19259b-4bc3-4df7-8a09-765794883524 --- EmbeddedPkg/Ebl/Command.c | 978 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 978 insertions(+) create mode 100644 EmbeddedPkg/Ebl/Command.c (limited to 'EmbeddedPkg/Ebl/Command.c') diff --git a/EmbeddedPkg/Ebl/Command.c b/EmbeddedPkg/Ebl/Command.c new file mode 100644 index 0000000000..7899a0f442 --- /dev/null +++ b/EmbeddedPkg/Ebl/Command.c @@ -0,0 +1,978 @@ +/** @file + Basic commands and command processing infrastructure for EBL + + Copyright (c) 2007, Intel Corporation
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "Ebl.h" +#include +#include + +UINTN mCmdTableMaxIndex = EBL_MAX_COMMAND_COUNT; +UINTN mCmdTableNextFreeIndex = 0; +EBL_COMMAND_TABLE *mCmdTable[EBL_MAX_COMMAND_COUNT]; + +/** + Converts a lowercase Ascii character to upper one + + If Chr is lowercase Ascii character, then converts it to upper one. + + If Value >= 0xA0, then ASSERT(). + If (Value & 0x0F) >= 0x0A, then ASSERT(). + + @param chr one Ascii character + + @return The uppercase value of Ascii character + +**/ +STATIC +CHAR8 +AsciiToUpper ( + IN CHAR8 Chr + ) +{ + return (UINT8) ((Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr); +} + + +/** + Case insensitve comparison of two Null-terminated Unicode strings with maximum + lengths, and returns the difference between the first mismatched Unicode + characters. + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. At most, Length Unicode + characters will be compared. If Length is 0, then 0 is returned. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched Unicode character in SecondString + subtracted from the first mismatched Unicode character in FirstString. + + @param FirstString Pointer to a Null-terminated ASCII string. + @param SecondString Pointer to a Null-terminated ASCII string. + @param Length Max length to compare. + + @retval 0 FirstString is identical to SecondString using case insensitive + comparisons. + @retval !=0 FirstString is not identical to SecondString using case + insensitive comparisons. + +**/ +INTN +EFIAPI +AsciiStrniCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ) +{ + if (Length == 0) { + return 0; + } + + while ((AsciiToUpper (*FirstString) != '\0') && + (AsciiToUpper (*FirstString) == AsciiToUpper (*SecondString)) && + (Length > 1)) { + FirstString++; + SecondString++; + Length--; + } + + return AsciiToUpper (*FirstString) - AsciiToUpper (*SecondString); +} + + + +/** + Add a command to the mCmdTable. If there is no free space in the command + table ASSERT. The mCmdTable is maintained in alphabetical order and the + new entry is inserted into its sorted possition. + + @param Entry Commnad Entry to add to the CmdTable + +**/ +VOID +EFIAPI +EblAddCommand ( + IN const EBL_COMMAND_TABLE *Entry + ) +{ + UINTN Count; + + if (mCmdTableNextFreeIndex == EBL_MAX_COMMAND_COUNT) { + // + // Ran out of space to store commands. Increase EBL_MAX_COMMAND_COUNT + // + ASSERT (FALSE); + return; + } + + // + // Add command and Insertion sort array in the process + // + mCmdTable[mCmdTableNextFreeIndex] = (EBL_COMMAND_TABLE *)Entry; + if (mCmdTableNextFreeIndex != 0) { + for (Count = mCmdTableNextFreeIndex; Count > 0; Count--) { + if (AsciiStriCmp (mCmdTable[Count - 1]->Name, Entry->Name) <= 0) { + break; + } + + mCmdTable[Count] = mCmdTable[Count - 1]; + } + mCmdTable[Count] = (EBL_COMMAND_TABLE *)Entry; + } + + mCmdTableNextFreeIndex++; +} + + +/** + Add an set of commands to the command table. Most commonly used on static + array of commands. + + @param EntryArray Pointer to array of command entries + @param ArrayCount Number of commnad entries to add + +**/ +VOID +EFIAPI +EblAddCommands ( + IN const EBL_COMMAND_TABLE *EntryArray, + IN UINTN ArrayCount + ) +{ + UINTN Index; + + for (Index = 0; Index < ArrayCount; Index++) { + EblAddCommand (&EntryArray[Index]); + } +} + + +EBL_ADD_COMMAND_PROTOCOL gEblAddCommand = { + EblAddCommand, + EblAddCommands, + EblGetCharKey, + EblAnyKeyToContinueQtoQuit +}; + + + +/** + Return the best matching command for the passed in command name. The match + does not have to be exact, it just needs to be unqiue. This enables commands + to be shortend to the smallest set of starting characters that is unique. + + @param CommandName Name of command to search for + + @return NULL CommandName did not match or was not unique + Other Pointer to EBL_COMMAND_TABLE entry for CommandName + +**/ +EBL_COMMAND_TABLE * +EblGetCommand ( + IN CHAR8 *CommandName + ) +{ + UINTN Index; + UINTN BestMatchCount; + UINTN Length; + EBL_COMMAND_TABLE *Match; + + Length = AsciiStrLen (CommandName); + for (Index = 0, BestMatchCount = 0, Match = NULL; Index < mCmdTableNextFreeIndex; Index++) { + if (AsciiStriCmp (mCmdTable[Index]->Name, CommandName) == 0) { + // match a command exactly + return mCmdTable[Index]; + } + + if (AsciiStrniCmp (CommandName, mCmdTable[Index]->Name, Length) == 0) { + // partial match, so keep looking to make sure there is only one partial match + BestMatchCount++; + Match = mCmdTable[Index]; + } + } + + if (BestMatchCount == 1) { + return Match; + } + + // + // We had no matches or too many matches + // + return NULL; +} + + + +/** + List out help information on all the commands or print extended information + about a specific passed in command. + + Argv[0] - "help" + Argv[1] - Command to display help about + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblHelpCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN Index; + CHAR8 *Ptr; + UINTN CurrentRow; + + if (Argc == 1) { + // Print all the commands + AsciiPrint ("Embedded Boot Loader (EBL) commands (help command for more info):\n"); + for (Index = 0; Index < mCmdTableNextFreeIndex; Index++) { + EblSetTextColor (EFI_YELLOW); + AsciiPrint (" %a", mCmdTable[Index]->Name); + EblSetTextColor (0); + AsciiPrint ("%a\n", mCmdTable[Index]->HelpSummary); + } + } else if (Argv[1] != NULL) { + // Print specific help + for (Index = 0, CurrentRow = 0; Index < mCmdTableNextFreeIndex; Index++) { + if (AsciiStriCmp (Argv[1], mCmdTable[Index]->Name) == 0) { + Ptr = (mCmdTable[Index]->Help == NULL) ? mCmdTable[Index]->HelpSummary : mCmdTable[Index]->Help; + AsciiPrint ("%a%a\n", Argv[1], Ptr); + if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) { + break; + } + } + } + } + + return EFI_SUCCESS; +} + + +/** + Exit the EBL. If the commnad processor sees EFI_ABORTED return status it will + exit the EBL. + + Argv[0] - "exit" + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_ABORTED + +**/ +EFI_STATUS +EblExitCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + UINTN MapKey; + UINTN DescriptorSize; + UINTN DescriptorVersion; + UINTN Pages; + + if (Argc > 1) { + if (AsciiStriCmp (Argv[1], "efi") != 0) { + return EFI_ABORTED; + } + } else if (Argc == 1) { + return EFI_ABORTED; + } + + 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)); + + // + // At this point it is very dangerous to do things EFI as most of EFI is now gone. + // This command is useful if you are working with a debugger as it will shutdown + // DMA and other things that could break a soft resets. + // + CpuDeadLoop (); + + // Should never get here, but makes the compiler happy + return EFI_ABORTED; +} + + +/** + Update the screen by decrementing the timeout value. + This AsciiPrint has to match the AsciiPrint in + EblPauseCmd. + + @param ElaspedTime Current timout value remaining + +**/ +VOID +EFIAPI +EblPauseCallback ( + IN UINTN ElapsedTime + ) +{ + AsciiPrint ("\b\b\b\b\b\b\b\b\b\b\b\b \b\b%3d seconds", ElapsedTime); +} + +/** + Pause until a key is pressed and abort the remaining commands on the command + line. If no key is pressed continue processing the command line. This command + allows the user to stop an operation from happening and return control to the + command prompt. + + Argv[0] - "pause" + Argv[1] - timeout value is decimal seconds + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS Timeout expired with no input + @return EFI_TIMEOUT Stop procesing other commands on the same command line + +**/ +EFI_STATUS +EblPauseCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + UINTN Delay; + EFI_INPUT_KEY Key; + + Delay = (Argc == 1)? 10 : AsciiStrDecimalToUintn (Argv[1]); + + AsciiPrint ("Hit any key to break. You have %3d seconds", Delay); + Status = EblGetCharKey (&Key, Delay, EblPauseCallback); + AsciiPrint ("\n"); + + // If we timeout then the pause succeded thus return success + // If we get a key return timout to stop other commnad on this cmd line + return (Status == EFI_SUCCESS) ? EFI_TIMEOUT : EFI_SUCCESS;; +} + + +/** + On a debug build issue a software breakpoint to enter the debugger + + Argv[0] - "break" + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblBreakPointCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + CpuBreakpoint (); + return EFI_SUCCESS; +} + + +/** + Reset the system. If no Argument do a Cold reset. If argument use that reset type + (W)arm = Warm Reset + (S)hutdown = Shutdown Reset + + Argv[0] - "reset" + Argv[1] - warm or shutdown reset type + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblResetCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_RESET_TYPE ResetType; + + ResetType = EfiResetCold; + if (Argc > 1) { + switch (*Argv[1]) { + case 'W': + case 'w': + ResetType = EfiResetWarm; + break; + case 'S': + case 's': + ResetType = EfiResetShutdown; + } + } + + gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL); + return EFI_SUCCESS; +} + + +/** + Toggle page break global. This turns on and off prompting to Quit or hit any + key to continue when a command is about to scroll the screen with its output + + Argv[0] - "page" + Argv[1] - on or off + + @param Argc Number of command arguments in Argv + @param Argv Array of strings that represent the parsed command line. + Argv[0] is the comamnd name + + @return EFI_SUCCESS + +**/ +EFI_STATUS +EblPageCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + if (Argc <= 1) { + // toggle setting + gPageBreak = (gPageBreak) ? FALSE : TRUE; + } else { + // use argv to set the value + if ((Argv[1][0] == 'o') || (Argv[1][0] == 'O')) { + if ((Argv[1][1] == 'n') || (Argv[1][1] == 'N')) { + gPageBreak = TRUE; + } else if ((Argv[1][1] == 'f') || (Argv[1][1] == 'F')) { + gPageBreak = FALSE; + } else { + return EFI_INVALID_PARAMETER; + } + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +EblSleepCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + UINTN Delay; + + Delay = (Argc == 1)? 10 : AsciiStrDecimalToUintn (Argv[1]); + + gBS->Stall (Delay * 1000000); + + return EFI_SUCCESS; +} + +CHAR8 +ConvertToTextLine ( + IN CHAR8 Character + ) +{ + if (Character < ' ' || Character > '~') + { + return '.'; + } + else + { + return Character; + } +} + +UINTN +GetBytes ( + IN UINT8 *Address, + IN UINTN Bytes + ) +{ + UINTN Result = 0; + + if (Bytes >= 1) + Result = *Address++; + + if (Bytes >= 2) + Result = (Result << 8) + *Address++; + + if (Bytes >= 3) + Result = (Result << 8) + *Address++; + + return Result; +} + +CHAR8 mBlanks[] = " "; + +EFI_STATUS +OutputData ( + IN UINT8 *Address, + IN UINTN Length, + IN UINTN Width, + IN UINTN Offset + ) +{ + UINT8 *EndAddress; + UINTN Line; + CHAR8 TextLine[0x11]; + UINTN CurrentRow = 0; + UINTN Bytes; + UINTN Spaces = 0; + CHAR8 Blanks[80]; + + AsciiStrCpy (Blanks, mBlanks); + for (EndAddress = Address + Length; Address < EndAddress; Offset += Line) + { + AsciiPrint ("%08x: ", Offset); + for (Line = 0; (Line < 0x10) && (Address < EndAddress);) + { + Bytes = EndAddress - Address; + + switch (Width) + { + case 4: + if (Bytes >= 4) + { + AsciiPrint ("%08x ", *((UINT32 *)Address)); + TextLine[Line++] = ConvertToTextLine(*Address++); + TextLine[Line++] = ConvertToTextLine(*Address++); + TextLine[Line++] = ConvertToTextLine(*Address++); + TextLine[Line++] = ConvertToTextLine(*Address++); + } + else + { + AsciiPrint ("%08x ", GetBytes(Address, Bytes)); + Address += Bytes; + Line += Bytes; + } + break; + + case 2: + if (Bytes >= 2) + { + AsciiPrint ("%04x ", *((UINT16 *)Address)); + TextLine[Line++] = ConvertToTextLine(*Address++); + TextLine[Line++] = ConvertToTextLine(*Address++); + } + else + { + AsciiPrint ("%04x ", GetBytes(Address, Bytes)); + Address += Bytes; + Line += Bytes; + } + break; + + case 1: + AsciiPrint ("%02x ", *((UINT8 *)Address)); + TextLine[Line++] = ConvertToTextLine(*Address++); + break; + + default: + AsciiPrint ("Width must be 1, 2, or 4!\n"); + return EFI_INVALID_PARAMETER; + } + } + + // Pad spaces + if (Line < 0x10) + { + switch (Width) + { + case 4: + Spaces = 9 * ((0x10 - Line)/4); + break; + case 2: + Spaces = 5 * ((0x10 - Line)/2); + break; + case 1: + Spaces = 3 * (0x10 - Line); + break; + } + + Blanks[Spaces] = '\0'; + + AsciiPrint(Blanks); + + Blanks[Spaces] = ' '; + } + + TextLine[Line] = 0; + AsciiPrint ("|%a|\n", TextLine); + + if (EblAnyKeyToContinueQtoQuit(&CurrentRow, FALSE)) + { + return EFI_END_OF_FILE; + } + } + + if (Length % Width != 0) + { + AsciiPrint ("%08x\n", Offset); + } + + return EFI_SUCCESS; +} + +#define HEXDUMP_CHUNK 1024 + +EFI_STATUS +EblHexdumpCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_OPEN_FILE *File; + VOID *Location; + UINTN Size; + UINTN Width = 1; + UINTN Offset = 0; + EFI_STATUS Status; + UINTN Chunk = HEXDUMP_CHUNK; + + if ((Argc < 2) || (Argc > 3)) + { + return EFI_INVALID_PARAMETER; + } + + if (Argc == 3) + { + Width = AsciiStrDecimalToUintn(Argv[2]); + } + + if ((Width != 1) && (Width != 2) && (Width != 4)) + { + return EFI_INVALID_PARAMETER; + } + + File = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0); + if (File == NULL) + { + return EFI_NOT_FOUND; + } + + Location = AllocatePool(Chunk); + Size = EfiTell(File, NULL); + + for (Offset = 0; Offset + HEXDUMP_CHUNK <= Size; Offset += Chunk) + { + Chunk = HEXDUMP_CHUNK; + + Status = EfiRead(File, Location, &Chunk); + if (EFI_ERROR(Status)) + { + AsciiPrint ("Error reading file content\n"); + goto Exit; + } + + Status = OutputData(Location, Chunk, Width, File->BaseOffset + Offset); + if (EFI_ERROR(Status)) + { + if (Status == EFI_END_OF_FILE) { + Status = EFI_SUCCESS; + } + goto Exit; + } + } + + // Any left over? + if (Offset < Size) + { + Chunk = Size - Offset; + Status = EfiRead(File, Location, &Chunk); + if (EFI_ERROR(Status)) + { + AsciiPrint ("Error reading file content\n"); + goto Exit; + } + + Status = OutputData(Location, Chunk, Width, File->BaseOffset + Offset); + if (EFI_ERROR(Status)) + { + if (Status == EFI_END_OF_FILE) { + Status = EFI_SUCCESS; + } + goto Exit; + } + } + +Exit: + EfiClose(File); + + FreePool(Location); + + return EFI_SUCCESS; +} + +#define USE_DISKIO 1 + +EFI_STATUS +EblDiskIoCmd ( + IN UINTN Argc, + IN CHAR8 **Argv + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINT8 *EndOffset; + UINTN Length; + UINTN Line; + UINT8 *Buffer; + UINT8 *BufferOffset; + CHAR8 TextLine[0x11]; +#if USE_DISKIO + EFI_DISK_IO_PROTOCOL *DiskIo; +#else + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINTN Lba; +#endif + + if (AsciiStrCmp(Argv[1], "r") == 0) + { + Offset = AsciiStrHexToUintn(Argv[2]); + Length = AsciiStrHexToUintn(Argv[3]); + +#if USE_DISKIO + Status = gBS->LocateProtocol(&gEfiDiskIoProtocolGuid, NULL, (VOID **)&DiskIo); + if (EFI_ERROR(Status)) + { + AsciiPrint("Did not locate DiskIO\n"); + return Status; + } + + Buffer = AllocatePool(Length); + BufferOffset = Buffer; + + Status = DiskIo->ReadDisk(DiskIo, SIGNATURE_32('f','l','s','h'), Offset, Length, Buffer); + if (EFI_ERROR(Status)) + { + AsciiPrint("DiskIO read failed\n"); + gBS->FreePool(Buffer); + return Status; + } +#else + Status = gBS->LocateProtocol(&gEfiBlockIoProtocolGuid, NULL, (VOID **)&BlockIo); + if (EFI_ERROR(Status)) + { + AsciiPrint("Did not locate BlockIo\n"); + return Status; + } + + Length = BlockIo->Media->BlockSize; + Buffer = AllocatePool(Length); + BufferOffset = Buffer; + Lba = Offset/BlockIo->Media->BlockSize; + + Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, Lba, Length, Buffer); + if (EFI_ERROR(Status)) + { + AsciiPrint("BlockIo read failed\n"); + gBS->FreePool(Buffer); + return Status; + } + + // Whack offset to what we actually read from + Offset = Lba * BlockIo->Media->BlockSize; + + Length = 0x100; +#endif + + for (EndOffset = BufferOffset + Length; BufferOffset < EndOffset; Offset += 0x10) + { + AsciiPrint ("%08x: ", Offset); + + for (Line = 0; Line < 0x10; Line++) + { + AsciiPrint ("%02x ", *BufferOffset); + + if (*BufferOffset < ' ' || *BufferOffset > '~') + TextLine[Line] = '.'; + else + TextLine[Line] = *BufferOffset; + + BufferOffset++; + } + + TextLine[Line] = '\0'; + AsciiPrint ("|%a|\n", TextLine); + } + + gBS->FreePool(Buffer); + + return EFI_SUCCESS; + } + else if (AsciiStrCmp(Argv[1], "w") == 0) + { + Offset = AsciiStrHexToUintn(Argv[2]); + Length = AsciiStrHexToUintn(Argv[3]); + Buffer = (UINT8 *)AsciiStrHexToUintn(Argv[4]); + +#if USE_DISKIO + Status = gBS->LocateProtocol(&gEfiDiskIoProtocolGuid, NULL, (VOID **)&DiskIo); + if (EFI_ERROR(Status)) + { + AsciiPrint("Did not locate DiskIO\n"); + return Status; + } + + Status = DiskIo->WriteDisk(DiskIo, SIGNATURE_32('f','l','s','h'), Offset, Length, Buffer); + if (EFI_ERROR(Status)) + { + AsciiPrint("DiskIO write failed\n"); + return Status; + } + +#else +#endif + + return EFI_SUCCESS; + } + else + { + return EFI_INVALID_PARAMETER; + } +} + +GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdTemplate[] = +{ + { + "reset", + " [type]; Reset system. type = [warm] [shutdown] default is cold reset", + NULL, + EblResetCmd + }, + { + "exit", + "; Exit EBL", + NULL, + EblExitCmd + }, + { + "help", + " [cmd]; Help on cmd or a list of all commands if cmd is ommited", + NULL, + EblHelpCmd + }, + { + "break", + "; Generate debugging breakpoint", + NULL, + EblBreakPointCmd + }, + { + "page", + " [on|off]]; toggle promting on command output larger than screen", + NULL, + EblPageCmd + }, + { + "pause", + " [sec]; Pause for sec[10] seconds. ", + NULL, + EblPauseCmd + }, + { + "sleep", + " [sec]; Sleep for sec[10] seconds. ", + NULL, + EblSleepCmd + }, + { + "hexdump", + " filename ; dump a file as hex bytes", + NULL, + EblHexdumpCmd + }, + { + "diskio", + " [r|w] offset [length [dataptr]]; do a DiskIO read or write ", + NULL, + EblDiskIoCmd + } +}; + + +EFI_HANDLE gExternalCmdHandle = NULL; + +/** + Initialize the commands in this in this file +**/ +VOID +EblInitializeCmdTable ( + VOID + ) +{ + + EblAddCommands (mCmdTemplate, sizeof (mCmdTemplate)/sizeof (EBL_COMMAND_TABLE)); + + gBS->InstallProtocolInterface ( + &gExternalCmdHandle, + &gEfiEblAddCommandProtocolGuid, + EFI_NATIVE_INTERFACE, + &gEblAddCommand + ); + +} + + +VOID +EblShutdownExternalCmdTable ( + VOID + ) +{ + gBS->UninstallProtocolInterface (gExternalCmdHandle, &gEfiEblAddCommandProtocolGuid, &gEblAddCommand); +} + + -- cgit v1.2.3