hikey: Add UEFI sources for reference

UEFI needs to be built outside Android build system.
Please follow the instructions in README.

The sources correspond to:
https://github.com/96boards/edk2/commit/14eae0c12e71fd33c4c0fc51e4475e8db02566cf
https://github.com/96boards/arm-trusted-firmware/commit/e9b4909dcd75fc4ae7041cfb83d28ab9adb7afdf
https://github.com/96boards/l-loader/commit/6b784ad5c4ab00e2b1c6f53cd5f74054e5d00a78
https://git.linaro.org/uefi/uefi-tools.git/commit/abe618f8ab72034fff1ce46c9c006a2c6bd40a7e

Change-Id: Ieeefdb63e673e0c8e64e0a1f02c7bddc63b2c7fb
Signed-off-by: Vishal Bhoj <vishal.bhoj@linaro.org>
diff --git a/uefi/linaro-edk2/EmbeddedPkg/Ebl/Main.c b/uefi/linaro-edk2/EmbeddedPkg/Ebl/Main.c
new file mode 100644
index 0000000..dc17d26
--- /dev/null
+++ b/uefi/linaro-edk2/EmbeddedPkg/Ebl/Main.c
@@ -0,0 +1,674 @@
+/** @file

+  Basic command line parser for EBL (Embedded Boot Loader)

+

+  Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>

+  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>

+

+  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

+    AsciiStrnCpy(&mCmdHistory[mCmdHistoryStart][0], 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

+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

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

+      AsciiStrnCpy (Cmd, 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)) {

+      UnicodeStrToAsciiStr(CommandLineVariable, CmdLine);

+    }

+

+    FreePool(CommandLineVariable);

+  }

+

+  if (EFI_ERROR(Status)) {

+    AsciiStrCpy (CmdLine, (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 ();

+    }

+  }

+}

+

+