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 ();
+ }
}
}