X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=EmbeddedPkg%2FEbl%2FMain.c;h=62f559fccfe8bbd8d2c775e13a19b943501d6a98;hb=d780544d3d1c67e2663e146e97c29bb2dc308172;hp=6d536fd79c242dad4b7c4d760c9e4216e8afb9a7;hpb=60274ccab831d7874129a6b6c271969418296960;p=mirror_edk2.git diff --git a/EmbeddedPkg/Ebl/Main.c b/EmbeddedPkg/Ebl/Main.c index 6d536fd79c..62f559fccf 100644 --- a/EmbeddedPkg/Ebl/Main.c +++ b/EmbeddedPkg/Ebl/Main.c @@ -3,6 +3,7 @@ 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 @@ -31,13 +32,13 @@ UINTN gScreenRows; // Global to turn on/off breaking commands with prompts before they scroll the screen BOOLEAN gPageBreak = TRUE; -VOID +VOID RingBufferIncrement ( IN INTN *Value ) { *Value = *Value + 1; - + if (*Value >= MAX_CMD_HISTORY) { *Value = 0; } @@ -49,14 +50,14 @@ RingBufferDecrement ( ) { *Value = *Value - 1; - + if (*Value < 0) { *Value = MAX_CMD_HISTORY - 1; } } /** - Save this command in the circular history buffer. Older commands are + Save this command in the circular history buffer. Older commands are overwritten with newer commands. @param Cmd Command line to archive the history of. @@ -71,7 +72,7 @@ SetCmdHistory ( { // Don't bother adding empty commands to the list if (AsciiStrLen(Cmd) != 0) { - + // First entry if (mCmdHistoryStart == -1) { mCmdHistoryStart = 0; @@ -79,19 +80,19 @@ SetCmdHistory ( } 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 - AsciiStrnCpy(&mCmdHistory[mCmdHistoryStart][0], Cmd, MAX_CMD_LINE); + AsciiStrnCpyS (&mCmdHistory[mCmdHistoryStart][0], MAX_CMD_LINE, Cmd, MAX_CMD_LINE); } - + // Reset the command history for the next up arrow press - mCmdHistoryCurrent = mCmdHistoryStart; + mCmdHistoryCurrent = mCmdHistoryStart; } @@ -110,48 +111,48 @@ GetCmdHistory ( ) { 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: +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 seperators are + 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. @@ -179,22 +180,22 @@ ParseArguments ( return NULL; } - // Walk a single command line. A CMD_SEPERATOR allows mult commands on a single line + // 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_SEPERATOR) { + if (!InQuote && *Char == CMD_SEPARATOR) { break; } - // Perform any text coversion here + // Perform any text conversion here if (*Char == '\t') { // TAB to space *Char = ' '; } if (LookingForArg) { - // Look for the beging of an Argv[] entry + // Look for the beginning of an Argv[] entry if (*Char == '"') { Argv[Arg++] = ++Char; LookingForArg = FALSE; @@ -202,20 +203,25 @@ ParseArguments ( } else if (*Char != ' ') { Argv[Arg++] = Char; LookingForArg = FALSE; - } + } } else { // Looking for the terminator of an Argv[] entry - if ((InQuote && (*Char == '"')) || (!InQuote && (*Char == ' '))) { + 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_SEPERATOR) { - // Replace the command delimeter with null and return pointer to next command line + if (*Char == CMD_SEPARATOR) { + // Replace the command delimiter with null and return pointer to next command line *Char = '\0'; return ++Char; } @@ -226,18 +232,19 @@ ParseArguments ( /** Return a keypress or optionally timeout if a timeout value was passed in. - An optional callback funciton is called evey second when waiting for a + 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 + @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, @@ -270,15 +277,15 @@ EblGetCharKey ( if (WaitCount == 2) { gBS->CloseEvent (WaitList[1]); } - return EFI_SUCCESS; + return EFI_SUCCESS; } break; case 1: - // Periodic 1 sec timer signaled + // Periodic 1 sec timer signaled TimeoutInSec--; if (CallBack != NULL) { - // Call the users callback function if registered + // Call the users callback function if registered CallBack (TimeoutInSec); } if (TimeoutInSec == 0) { @@ -289,7 +296,7 @@ EblGetCharKey ( default: ASSERT (FALSE); } - } + } } @@ -300,7 +307,7 @@ EblGetCharKey ( 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 + 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 @@ -310,6 +317,7 @@ EblGetCharKey ( **/ BOOLEAN +EFIAPI EblAnyKeyToContinueQtoQuit ( IN UINTN *CurrentRow, IN BOOLEAN PrefixNewline @@ -344,7 +352,7 @@ EblAnyKeyToContinueQtoQuit ( /** - Set the text color of the EFI Console. If a zero is passed in reset to + 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 @@ -365,14 +373,14 @@ EblSetTextColor ( /** - Collect the keyboard input for a cmd line. Carage Return, New Line, or ESC + 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 commnad line is possible without deletion at this time! - The up arrow and down arrow fill Cmd with information from the history + 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 Cmd Command line to return @param CmdMaxSize Maximum size of Cmd @return The Status of EblGetCharKey() @@ -424,7 +432,7 @@ GetCmd ( } AsciiPrint (History); Index = AsciiStrLen (History); - AsciiStrnCpy (Cmd, History, CmdMaxSize); + AsciiStrnCpyS (Cmd, CmdMaxSize, History, CmdMaxSize); } else { Cmd[Index++] = Char; if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) { @@ -455,6 +463,45 @@ EblPrintStartupBanner ( } +/** + 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. **/ @@ -464,7 +511,7 @@ EblPrompt ( ) { EblSetTextColor (EFI_YELLOW); - AsciiPrint ((CHAR8 *)PcdGetPtr (PcdEmbeddedPrompt), EfiGetCwd ()); + AsciiPrint ("%a %a",(CHAR8 *)PcdGetPtr (PcdEmbeddedPrompt), EfiGetCwd ()); EblSetTextColor (0); AsciiPrint ("%a", ">"); } @@ -472,12 +519,12 @@ EblPrompt ( /** - Parse a command line and execute the commands. The ; seperator allows + 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 + @param MaxCmdLineSize MaxSize of the Command line @return EFI status of the Command @@ -494,7 +541,7 @@ ProcessCmdLine ( UINTN Argc; CHAR8 *Argv[MAX_ARGS]; - // Parse the command line. The loop processes commands seperated by ; + // 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) { @@ -506,32 +553,34 @@ ProcessCmdLine ( // exit command so lets exit break; } else if (Status == EFI_TIMEOUT) { - // pause command got imput so don't process any more cmd on this cmd line + // 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 commnad line that - gets executed automatically. The ; seperator allows multiple commands + 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 applicaiton + @return EFI status of the application **/ EFI_STATUS @@ -539,7 +588,7 @@ EFIAPI EdkBootLoaderEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable - ) + ) { EFI_STATUS Status; CHAR8 CmdLine[MAX_CMD_LINE]; @@ -548,7 +597,7 @@ EdkBootLoaderEntry ( UINTN CommandLineVariableSize = 0; EFI_GUID VendorGuid; - // Initialize tables of commnads + // Initialize tables of commands EblInitializeCmdTable (); EblInitializeDeviceCmd (); EblInitializemdHwDebugCmds (); @@ -558,7 +607,13 @@ EdkBootLoaderEntry ( 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); @@ -576,29 +631,29 @@ EdkBootLoaderEntry ( gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &gScreenColumns, &gScreenRows); EblPrintStartupBanner (); - - // Parse command line and handle commands seperated by ; + + // 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)) { - UnicodeStrToAsciiStr(CommandLineVariable, CmdLine); + UnicodeStrToAsciiStrS (CommandLineVariable, CmdLine, MAX_CMD_LINE); } - + FreePool(CommandLineVariable); } - + if (EFI_ERROR(Status)) { - AsciiStrCpy (CmdLine, (CHAR8 *)PcdGetPtr (PcdEmbeddedAutomaticBootCommand)); + AsciiStrCpyS (CmdLine, MAX_CMD_LINE, (CHAR8 *)PcdGetPtr (PcdEmbeddedAutomaticBootCommand)); } - + for (;;) { Status = ProcessCmdLine (CmdLine, MAX_CMD_LINE); if (Status == EFI_ABORTED) { @@ -611,6 +666,11 @@ EdkBootLoaderEntry ( 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 (); + } } }