X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=EmbeddedPkg%2FEbl%2FMain.c;fp=EmbeddedPkg%2FEbl%2FMain.c;h=0000000000000000000000000000000000000000;hp=62f559fccfe8bbd8d2c775e13a19b943501d6a98;hb=5604d269ab384543c6459c825c3c8c5eb71c435b;hpb=d780544d3d1c67e2663e146e97c29bb2dc308172 diff --git a/EmbeddedPkg/Ebl/Main.c b/EmbeddedPkg/Ebl/Main.c deleted file mode 100644 index 62f559fccf..0000000000 --- a/EmbeddedPkg/Ebl/Main.c +++ /dev/null @@ -1,677 +0,0 @@ -/** @file - Basic command line parser for EBL (Embedded Boot Loader) - - Copyright (c) 2007, Intel Corporation. All rights reserved.
- Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
- (C) Copyright 2015 Hewlett Packard Enterprise Development LP
- - 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" - -// Globals for command history processing -INTN mCmdHistoryEnd = -1; -INTN mCmdHistoryStart = -1; -INTN mCmdHistoryCurrent = -1; -CHAR8 mCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LINE]; -CHAR8 *mCmdBlank = ""; - -// Globals to remember current screen geometry -UINTN gScreenColumns; -UINTN gScreenRows; - -// Global to turn on/off breaking commands with prompts before they scroll the screen -BOOLEAN gPageBreak = TRUE; - -VOID -RingBufferIncrement ( - IN INTN *Value - ) -{ - *Value = *Value + 1; - - if (*Value >= MAX_CMD_HISTORY) { - *Value = 0; - } -} - -VOID -RingBufferDecrement ( - IN INTN *Value - ) -{ - *Value = *Value - 1; - - if (*Value < 0) { - *Value = MAX_CMD_HISTORY - 1; - } -} - -/** - Save this command in the circular history buffer. Older commands are - overwritten with newer commands. - - @param Cmd Command line to archive the history of. - - @return None - -**/ -VOID -SetCmdHistory ( - IN CHAR8 *Cmd - ) -{ - // Don't bother adding empty commands to the list - if (AsciiStrLen(Cmd) != 0) { - - // First entry - if (mCmdHistoryStart == -1) { - mCmdHistoryStart = 0; - mCmdHistoryEnd = 0; - } else { - // Record the new command at the next index - RingBufferIncrement(&mCmdHistoryStart); - - // If the next index runs into the end index, shuffle end back by one - if (mCmdHistoryStart == mCmdHistoryEnd) { - RingBufferIncrement(&mCmdHistoryEnd); - } - } - - // Copy the new command line into the ring buffer - AsciiStrnCpyS (&mCmdHistory[mCmdHistoryStart][0], MAX_CMD_LINE, Cmd, MAX_CMD_LINE); - } - - // Reset the command history for the next up arrow press - mCmdHistoryCurrent = mCmdHistoryStart; -} - - -/** - Retreave data from the Command History buffer. Direction maps into up arrow - an down arrow on the command line - - @param Direction Command forward or back - - @return The Command history based on the Direction - -**/ -CHAR8 * -GetCmdHistory ( - IN UINT16 Direction - ) -{ - CHAR8 *HistoricalCommand = NULL; - - // No history yet? - if (mCmdHistoryCurrent == -1) { - HistoricalCommand = mCmdBlank; - goto Exit; - } - - if (Direction == SCAN_UP) { - HistoricalCommand = &mCmdHistory[mCmdHistoryCurrent][0]; - - // if we just echoed the last command, hang out there, don't wrap around - if (mCmdHistoryCurrent == mCmdHistoryEnd) { - goto Exit; - } - - // otherwise, back up by one - RingBufferDecrement(&mCmdHistoryCurrent); - - } else if (Direction == SCAN_DOWN) { - - // if we last echoed the start command, put a blank prompt out - if (mCmdHistoryCurrent == mCmdHistoryStart) { - HistoricalCommand = mCmdBlank; - goto Exit; - } - - // otherwise increment the current pointer and return that command - RingBufferIncrement(&mCmdHistoryCurrent); - RingBufferIncrement(&mCmdHistoryCurrent); - - HistoricalCommand = &mCmdHistory[mCmdHistoryCurrent][0]; - RingBufferDecrement(&mCmdHistoryCurrent); - } - -Exit: - return HistoricalCommand; -} - - -/** - Parse the CmdLine and break it up into Argc (arg count) and Argv (array of - pointers to each argument). The Cmd buffer is altered and separators are - converted to string terminators. This allows Argv to point into CmdLine. - A CmdLine can support multiple commands. The next command in the command line - is returned if it exists. - - @param CmdLine String to parse for a set of commands - @param Argc Returns the number of arguments in the CmdLine current command - @param Argv Argc pointers to each string in CmdLine - - @return Next Command in the command line or NULL if non exists -**/ -CHAR8 * -ParseArguments ( - IN CHAR8 *CmdLine, - OUT UINTN *Argc, - OUT CHAR8 **Argv - ) -{ - UINTN Arg; - CHAR8 *Char; - BOOLEAN LookingForArg; - BOOLEAN InQuote; - - *Argc = 0; - if (AsciiStrLen (CmdLine) == 0) { - return NULL; - } - - // Walk a single command line. A CMD_SEPARATOR allows multiple commands on a single line - InQuote = FALSE; - LookingForArg = TRUE; - for (Char = CmdLine, Arg = 0; *Char != '\0'; Char++) { - if (!InQuote && *Char == CMD_SEPARATOR) { - break; - } - - // Perform any text conversion here - if (*Char == '\t') { - // TAB to space - *Char = ' '; - } - - if (LookingForArg) { - // Look for the beginning of an Argv[] entry - if (*Char == '"') { - Argv[Arg++] = ++Char; - LookingForArg = FALSE; - InQuote = TRUE; - } else if (*Char != ' ') { - Argv[Arg++] = Char; - LookingForArg = FALSE; - } - } else { - // Looking for the terminator of an Argv[] entry - if (!InQuote && (*Char == ' ')) { - *Char = '\0'; - LookingForArg = TRUE; - } else if (!InQuote && (*Char == '"') && (*(Char-1) != '\\')) { - InQuote = TRUE; - } else if (InQuote && (*Char == '"') && (*(Char-1) != '\\')) { - *Char = '\0'; - InQuote = FALSE; - } - } - } - - *Argc = Arg; - - if (*Char == CMD_SEPARATOR) { - // Replace the command delimiter with null and return pointer to next command line - *Char = '\0'; - return ++Char; - } - - return NULL; -} - - -/** - Return a keypress or optionally timeout if a timeout value was passed in. - An optional callback function is called every second when waiting for a - timeout. - - @param Key EFI Key information returned - @param TimeoutInSec Number of seconds to wait to timeout - @param CallBack Callback called every second during the timeout wait - - @return EFI_SUCCESS Key was returned - @return EFI_TIMEOUT If the TimoutInSec expired - -**/ -EFI_STATUS -EFIAPI -EblGetCharKey ( - IN OUT EFI_INPUT_KEY *Key, - IN UINTN TimeoutInSec, - IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL - ) -{ - EFI_STATUS Status; - UINTN WaitCount; - UINTN WaitIndex; - EFI_EVENT WaitList[2]; - - WaitCount = 1; - WaitList[0] = gST->ConIn->WaitForKey; - if (TimeoutInSec != 0) { - // Create a time event for 1 sec duration if we have a timeout - gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &WaitList[1]); - gBS->SetTimer (WaitList[1], TimerPeriodic, EFI_SET_TIMER_TO_SECOND); - WaitCount++; - } - - for (;;) { - Status = gBS->WaitForEvent (WaitCount, WaitList, &WaitIndex); - ASSERT_EFI_ERROR (Status); - - switch (WaitIndex) { - case 0: - // Key event signaled - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key); - if (!EFI_ERROR (Status)) { - if (WaitCount == 2) { - gBS->CloseEvent (WaitList[1]); - } - return EFI_SUCCESS; - } - break; - - case 1: - // Periodic 1 sec timer signaled - TimeoutInSec--; - if (CallBack != NULL) { - // Call the users callback function if registered - CallBack (TimeoutInSec); - } - if (TimeoutInSec == 0) { - gBS->CloseEvent (WaitList[1]); - return EFI_TIMEOUT; - } - break; - default: - ASSERT (FALSE); - } - } -} - - -/** - This routine is used prevent command output data from scrolling off the end - of the screen. The global gPageBreak is used to turn on or off this feature. - If the CurrentRow is near the end of the screen pause and print out a prompt - If the use hits Q to quit return TRUE else for any other key return FALSE. - PrefixNewline is used to figure out if a newline is needed before the prompt - string. This depends on the last print done before calling this function. - CurrentRow is updated by one on a call or set back to zero if a prompt is - needed. - - @param CurrentRow Used to figure out if its the end of the page and updated - @param PrefixNewline Did previous print issue a newline - - @return TRUE if Q was hit to quit, FALSE in all other cases. - -**/ -BOOLEAN -EFIAPI -EblAnyKeyToContinueQtoQuit ( - IN UINTN *CurrentRow, - IN BOOLEAN PrefixNewline - ) -{ - EFI_INPUT_KEY InputKey; - - if (!gPageBreak) { - // global disable for this feature - return FALSE; - } - - if (*CurrentRow >= (gScreenRows - 2)) { - if (PrefixNewline) { - AsciiPrint ("\n"); - } - AsciiPrint ("Any key to continue (Q to quit): "); - EblGetCharKey (&InputKey, 0, NULL); - AsciiPrint ("\n"); - - // Time to promt to stop the screen. We have to leave space for the prompt string - *CurrentRow = 0; - if (InputKey.UnicodeChar == 'Q' || InputKey.UnicodeChar == 'q') { - return TRUE; - } - } else { - *CurrentRow += 1; - } - - return FALSE; -} - - -/** - Set the text color of the EFI Console. If a zero is passed in reset to - default text/background color. - - @param Attribute For text and background color - -**/ -VOID -EblSetTextColor ( - UINTN Attribute - ) -{ - if (Attribute == 0) { - // Set the text color back to default - Attribute = (UINTN)PcdGet32 (PcdEmbeddedDefaultTextColor); - } - - gST->ConOut->SetAttribute (gST->ConOut, Attribute); -} - - -/** - Collect the keyboard input for a cmd line. Carriage Return, New Line, or ESC - terminates the command line. You can edit the command line via left arrow, - delete and backspace and they all back up and erase the command line. - No edit of command line is possible without deletion at this time! - The up arrow and down arrow fill Cmd with information from the history - buffer. - - @param Cmd Command line to return - @param CmdMaxSize Maximum size of Cmd - - @return The Status of EblGetCharKey() - -**/ -EFI_STATUS -GetCmd ( - IN OUT CHAR8 *Cmd, - IN UINTN CmdMaxSize - ) -{ - EFI_STATUS Status; - UINTN Index; - UINTN Index2; - CHAR8 Char; - CHAR8 *History; - EFI_INPUT_KEY Key; - - for (Index = 0; Index < CmdMaxSize - 1;) { - Status = EblGetCharKey (&Key, 0, NULL); - if (EFI_ERROR (Status)) { - Cmd[Index] = '\0'; - AsciiPrint ("\n"); - return Status; - } - - Char = (CHAR8)Key.UnicodeChar; - if ((Char == '\n') || (Char == '\r') || (Char == 0x7f)) { - Cmd[Index] = '\0'; - if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) { - AsciiPrint ("\n\r"); - } - return EFI_SUCCESS; - } else if ((Char == '\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){ - if (Index != 0) { - Index--; - // - // Update the display - // - AsciiPrint ("\b \b"); - } - } else if ((Key.ScanCode == SCAN_UP) || Key.ScanCode == SCAN_DOWN) { - History = GetCmdHistory (Key.ScanCode); - // - // Clear display line - // - for (Index2 = 0; Index2 < Index; Index2++) { - AsciiPrint ("\b \b"); - } - AsciiPrint (History); - Index = AsciiStrLen (History); - AsciiStrnCpyS (Cmd, CmdMaxSize, History, CmdMaxSize); - } else { - Cmd[Index++] = Char; - if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) { - AsciiPrint ("%c", Char); - } - } - } - - return EFI_SUCCESS; -} - - -/** - Print the boot up banner for the EBL. -**/ -VOID -EblPrintStartupBanner ( - VOID - ) -{ - AsciiPrint ("Embedded Boot Loader ("); - EblSetTextColor (EFI_YELLOW); - AsciiPrint ("EBL"); - EblSetTextColor (0); - AsciiPrint (") prototype. Built at %a on %a\n",__TIME__, __DATE__); - AsciiPrint ("THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN 'AS IS' BASIS,\nWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\n"); - AsciiPrint ("Please send feedback to edk2-devel@lists.sourceforge.net\n"); -} - - -/** - Send null requests to all removable media block IO devices so the a media add/remove/change - can be detected in real before we execute a command. - - This is mainly due to the fact that the FAT driver does not do this today so you can get stale - dir commands after an SD Card has been removed. -**/ -VOID -EblProbeRemovableMedia ( - VOID - ) -{ - UINTN Index; - UINTN Max; - EFI_OPEN_FILE *File; - - // - // Probe for media insertion/removal in removable media devices - // - Max = EfiGetDeviceCounts (EfiOpenBlockIo); - if (Max != 0) { - for (Index = 0; Index < Max; Index++) { - File = EfiDeviceOpenByType (EfiOpenBlockIo, Index); - if (File != NULL) { - if (File->FsBlockIoMedia->RemovableMedia) { - // Probe to see if media is present (or not) or media changed - // this causes the ReinstallProtocolInterface() to fire in the - // block io driver to update the system about media change events - File->FsBlockIo->ReadBlocks (File->FsBlockIo, File->FsBlockIo->Media->MediaId, (EFI_LBA)0, 0, NULL); - } - EfiClose (File); - } - } - } -} - - - - -/** - Print the prompt for the EBL. -**/ -VOID -EblPrompt ( - VOID - ) -{ - EblSetTextColor (EFI_YELLOW); - AsciiPrint ("%a %a",(CHAR8 *)PcdGetPtr (PcdEmbeddedPrompt), EfiGetCwd ()); - EblSetTextColor (0); - AsciiPrint ("%a", ">"); -} - - - -/** - Parse a command line and execute the commands. The ; separator allows - multiple commands for each command line. Stop processing if one of the - commands returns an error. - - @param CmdLine Command Line to process. - @param MaxCmdLineSize MaxSize of the Command line - - @return EFI status of the Command - -**/ -EFI_STATUS -ProcessCmdLine ( - IN CHAR8 *CmdLine, - IN UINTN MaxCmdLineSize - ) -{ - EFI_STATUS Status; - EBL_COMMAND_TABLE *Cmd; - CHAR8 *Ptr; - UINTN Argc; - CHAR8 *Argv[MAX_ARGS]; - - // Parse the command line. The loop processes commands separated by ; - for (Ptr = CmdLine, Status = EFI_SUCCESS; Ptr != NULL;) { - Ptr = ParseArguments (Ptr, &Argc, Argv); - if (Argc != 0) { - Cmd = EblGetCommand (Argv[0]); - if (Cmd != NULL) { - // Execute the Command! - Status = Cmd->Command (Argc, Argv); - if (Status == EFI_ABORTED) { - // exit command so lets exit - break; - } else if (Status == EFI_TIMEOUT) { - // pause command got input so don't process any more cmd on this cmd line - break; - } else if (EFI_ERROR (Status)) { - AsciiPrint ("%a returned %r error\n", Cmd->Name, Status); - // if any command fails stop processing CmdLine - break; - } - } else { - AsciiPrint ("The command '%a' is not supported.\n", Argv[0]); - } - } - } - - return Status; -} - - - -/** - Embedded Boot Loader (EBL) - A simple EFI command line application for embedded - devices. PcdEmbeddedAutomaticBootCommand is a complied in command line that - gets executed automatically. The ; separator allows multiple commands - for each command line. - - @param ImageHandle EFI ImageHandle for this application. - @param SystemTable EFI system table - - @return EFI status of the application - -**/ -EFI_STATUS -EFIAPI -EdkBootLoaderEntry ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - CHAR8 CmdLine[MAX_CMD_LINE]; - CHAR16 *CommandLineVariable = NULL; - CHAR16 *CommandLineVariableName = L"default-cmdline"; - UINTN CommandLineVariableSize = 0; - EFI_GUID VendorGuid; - - // Initialize tables of commands - EblInitializeCmdTable (); - EblInitializeDeviceCmd (); - EblInitializemdHwDebugCmds (); - EblInitializemdHwIoDebugCmds (); - EblInitializeDirCmd (); - EblInitializeHobCmd (); - EblInitializeScriptCmd (); - EblInitializeExternalCmd (); - EblInitializeNetworkCmd(); - EblInitializeVariableCmds (); - - if (gST->ConOut == NULL) { - DEBUG((EFI_D_ERROR,"Error: No Console Output\n")); - return EFI_NOT_READY; - } - - // Disable the 5 minute EFI watchdog time so we don't get automatically reset - gBS->SetWatchdogTimer (0, 0, 0, NULL); - - if (FeaturePcdGet (PcdEmbeddedMacBoot)) { - // A MAC will boot in graphics mode, so turn it back to text here - // This protocol was removed from edk2. It is only an edk thing. We need to make our own copy. - // DisableQuietBoot (); - - // Enable the biggest output screen size possible - gST->ConOut->SetMode (gST->ConOut, (UINTN)gST->ConOut->Mode->MaxMode - 1); - - } - - // Save current screen mode - gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &gScreenColumns, &gScreenRows); - - EblPrintStartupBanner (); - - // Parse command line and handle commands separated by ; - // The loop prints the prompt gets user input and saves history - - // Look for a variable with a default command line, otherwise use the Pcd - ZeroMem(&VendorGuid, sizeof(EFI_GUID)); - - Status = gRT->GetVariable(CommandLineVariableName, &VendorGuid, NULL, &CommandLineVariableSize, CommandLineVariable); - if (Status == EFI_BUFFER_TOO_SMALL) { - CommandLineVariable = AllocatePool(CommandLineVariableSize); - - Status = gRT->GetVariable(CommandLineVariableName, &VendorGuid, NULL, &CommandLineVariableSize, CommandLineVariable); - if (!EFI_ERROR(Status)) { - UnicodeStrToAsciiStrS (CommandLineVariable, CmdLine, MAX_CMD_LINE); - } - - FreePool(CommandLineVariable); - } - - if (EFI_ERROR(Status)) { - AsciiStrCpyS (CmdLine, MAX_CMD_LINE, (CHAR8 *)PcdGetPtr (PcdEmbeddedAutomaticBootCommand)); - } - - for (;;) { - Status = ProcessCmdLine (CmdLine, MAX_CMD_LINE); - if (Status == EFI_ABORTED) { - // if a command returns EFI_ABORTED then exit the EBL - EblShutdownExternalCmdTable (); - return EFI_SUCCESS; - } - - // get the command line from the user - EblPrompt (); - GetCmd (CmdLine, MAX_CMD_LINE); - SetCmdHistory (CmdLine); - - if (FeaturePcdGet (PcdEmbeddedProbeRemovable)) { - // Probe removable media devices to see if media has been inserted or removed. - EblProbeRemovableMedia (); - } - } -} - -