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
This commit is contained in:
65
EmbeddedPkg/Ebl/CmdTemplate.c
Normal file
65
EmbeddedPkg/Ebl/CmdTemplate.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/** @file
|
||||
%CommandName% for EBL (Embedded Boot Loader)
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
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.
|
||||
|
||||
Module Name: CmdTemplate.c
|
||||
|
||||
Search/Replace %CommandName% with the name of your new command
|
||||
|
||||
**/
|
||||
|
||||
#include "Ebl.h"
|
||||
|
||||
|
||||
/**
|
||||
Fill Me In
|
||||
|
||||
Argv[0] - "%CommandName%"
|
||||
|
||||
@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
|
||||
Ebl%CommandName%Cmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmd%CommandName%Template[] =
|
||||
{
|
||||
{
|
||||
"%CommandName%",
|
||||
" [show args] ; explain args and command",
|
||||
NULL,
|
||||
Ebl%CommandName%Cmd
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Initialize the commands in this in this file
|
||||
**/
|
||||
VOID
|
||||
EblInitialize%CommandName%Cmd (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EblAddCommands (mCmd%CommandName%Template, sizeof (mCmd%CommandName%Template)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
|
978
EmbeddedPkg/Ebl/Command.c
Normal file
978
EmbeddedPkg/Ebl/Command.c
Normal file
@@ -0,0 +1,978 @@
|
||||
/** @file
|
||||
Basic commands and command processing infrastructure for EBL
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
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 <Protocol/DiskIo.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
305
EmbeddedPkg/Ebl/Dir.c
Normal file
305
EmbeddedPkg/Ebl/Dir.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/** @file
|
||||
Dir for EBL (Embedded Boot Loader)
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
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.
|
||||
|
||||
Module Name: CmdTemplate.c
|
||||
|
||||
Search/Replace Dir with the name of your new command
|
||||
|
||||
**/
|
||||
|
||||
#include "Ebl.h"
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *gFvFileType[] = {
|
||||
"All",
|
||||
"Raw",
|
||||
"Freeform",
|
||||
"SEC",
|
||||
"PeiCore",
|
||||
"DxeCore",
|
||||
"PEIM",
|
||||
"Driver",
|
||||
"Combo Driver",
|
||||
"Application",
|
||||
"NULL",
|
||||
"FV"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Perform a dir on a device. The device must support Simple File System Protocol
|
||||
or the FV protocol.
|
||||
|
||||
Argv[0] - "dir"
|
||||
Argv[1] - Device Name:path. Path is optional
|
||||
Argv[2] - Optional filename to match on. A leading * means match substring
|
||||
Argv[3] - Optional FV file type
|
||||
|
||||
dir fs1:\efi ; perform a dir on fs1: device in the efi directory
|
||||
dir fs1:\efi *.efi; perform a dir on fs1: device in the efi directory but
|
||||
only print out files that contain the string *.efi
|
||||
dir fv1:\ ; perform a dir on fv1: device in the efi directory
|
||||
NOTE: fv devices do not contian subdirs
|
||||
dir fv1:\ * PEIM ; will match all files of type SEC
|
||||
|
||||
@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
|
||||
EblDirCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_OPEN_FILE *File;
|
||||
EFI_FILE_INFO *DirInfo;
|
||||
UINTN ReadSize;
|
||||
UINTN CurrentRow;
|
||||
CHAR16 *MatchSubString;
|
||||
EFI_STATUS GetNextFileStatus;
|
||||
UINTN Key;
|
||||
EFI_FV_FILETYPE SearchType;
|
||||
EFI_FV_FILETYPE Type;
|
||||
EFI_FV_FILE_ATTRIBUTES Attributes;
|
||||
UINTN Size;
|
||||
EFI_GUID NameGuid;
|
||||
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
|
||||
UINT32 AuthenticationStatus;
|
||||
VOID *Section;
|
||||
UINTN SectionSize;
|
||||
EFI_FV_FILETYPE Index;
|
||||
UINTN Length;
|
||||
UINTN BestMatchCount;
|
||||
CHAR16 UnicodeFileName[MAX_CMD_LINE];
|
||||
|
||||
|
||||
if (Argc <= 1) {
|
||||
// CWD not currently supported
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (File->Type == EfiOpenFirmwareVolume) {
|
||||
// FV Dir
|
||||
|
||||
SearchType = EFI_FV_FILETYPE_ALL;
|
||||
UnicodeFileName[0] = '\0';
|
||||
MatchSubString = &UnicodeFileName[0];
|
||||
if (Argc > 2) {
|
||||
AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);
|
||||
if (UnicodeFileName[0] == '*') {
|
||||
// Handle *Name substring matching
|
||||
MatchSubString = &UnicodeFileName[1];
|
||||
}
|
||||
|
||||
// Handle file type matchs
|
||||
if (Argc > 3) {
|
||||
// match a specific file type, always last argument
|
||||
Length = AsciiStrLen (Argv[3]);
|
||||
for (Index = 1, BestMatchCount = 0; Index < sizeof (gFvFileType)/sizeof (CHAR8 *); Index++) {
|
||||
if (AsciiStriCmp (gFvFileType[Index], Argv[3]) == 0) {
|
||||
// exact match
|
||||
SearchType = Index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (AsciiStrniCmp (Argv[3], gFvFileType[Index], Length) == 0) {
|
||||
// partial match, so keep looking to make sure there is only one partial match
|
||||
BestMatchCount++;
|
||||
SearchType = Index;
|
||||
}
|
||||
}
|
||||
|
||||
if (BestMatchCount > 1) {
|
||||
SearchType = EFI_FV_FILETYPE_ALL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Fv = File->Fv;
|
||||
Key = 0;
|
||||
CurrentRow = 0;
|
||||
do {
|
||||
Type = SearchType;
|
||||
GetNextFileStatus = Fv->GetNextFile (
|
||||
Fv,
|
||||
&Key,
|
||||
&Type,
|
||||
&NameGuid,
|
||||
&Attributes,
|
||||
&Size
|
||||
);
|
||||
if (!EFI_ERROR (GetNextFileStatus)) {
|
||||
// Calculate size of entire file
|
||||
Section = NULL;
|
||||
Size = 0;
|
||||
Status = Fv->ReadFile (
|
||||
Fv,
|
||||
&NameGuid,
|
||||
Section,
|
||||
&Size,
|
||||
&Type,
|
||||
&Attributes,
|
||||
&AuthenticationStatus
|
||||
);
|
||||
if (!((Status == EFI_BUFFER_TOO_SMALL) || !EFI_ERROR (Status))) {
|
||||
// EFI_SUCCESS or EFI_BUFFER_TOO_SMALL mean size is valid
|
||||
Size = 0;
|
||||
}
|
||||
|
||||
// read the UI seciton to do a name match.
|
||||
Section = NULL;
|
||||
Status = Fv->ReadSection (
|
||||
Fv,
|
||||
&NameGuid,
|
||||
EFI_SECTION_USER_INTERFACE,
|
||||
0,
|
||||
&Section,
|
||||
&SectionSize,
|
||||
&AuthenticationStatus
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
if (StrStr (Section, MatchSubString) != NULL) {
|
||||
AsciiPrint (" %g %s %a %,d\n", &NameGuid, Section, gFvFileType[Type], Size);
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
FreePool (Section);
|
||||
} else {
|
||||
if (*MatchSubString == '\0') {
|
||||
AsciiPrint (" %g %a %,d\n", &NameGuid, gFvFileType[Type], Size);
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!EFI_ERROR (GetNextFileStatus));
|
||||
|
||||
} else if ((File->Type == EfiOpenFileSystem) || (File->Type == EfiOpenBlockIo)) {
|
||||
// Simple File System DIR
|
||||
|
||||
if (File->FsFileInfo == NULL) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (!(File->FsFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// Handle *Name substring matching
|
||||
MatchSubString = NULL;
|
||||
UnicodeFileName[0] = '\0';
|
||||
if (Argc > 2) {
|
||||
AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);
|
||||
if (UnicodeFileName[0] == '*') {
|
||||
MatchSubString = &UnicodeFileName[1];
|
||||
}
|
||||
}
|
||||
|
||||
File->FsFileHandle->SetPosition (File->FsFileHandle, 0);
|
||||
for (CurrentRow = 0;;) {
|
||||
// First read gets the size
|
||||
DirInfo = NULL;
|
||||
ReadSize = 0;
|
||||
Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
// Allocate the buffer for the real read
|
||||
DirInfo = AllocatePool (ReadSize);
|
||||
if (DirInfo == NULL) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
// Read the data
|
||||
Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
|
||||
if ((EFI_ERROR (Status)) || (ReadSize == 0)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (MatchSubString != NULL) {
|
||||
if (StrStr (&DirInfo->FileName[0], MatchSubString) == NULL) {
|
||||
// does not match *name argument, so skip
|
||||
continue;
|
||||
}
|
||||
} else if (UnicodeFileName[0] != '\0') {
|
||||
// is not an exact match for name argument, so skip
|
||||
if (StrCmp (&DirInfo->FileName[0], UnicodeFileName) != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (DirInfo->Attribute & EFI_FILE_DIRECTORY) {
|
||||
AsciiPrint (" <DIR> %s\n", &DirInfo->FileName[0]);
|
||||
} else {
|
||||
AsciiPrint ("%,14ld %s\n", DirInfo->FileSize, &DirInfo->FileName[0]);
|
||||
}
|
||||
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
FreePool (DirInfo);
|
||||
}
|
||||
|
||||
Done:
|
||||
if (DirInfo != NULL) {
|
||||
FreePool (DirInfo);
|
||||
}
|
||||
}
|
||||
|
||||
EfiClose (File);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDirTemplate[] =
|
||||
{
|
||||
{
|
||||
"dir",
|
||||
" dirdev [*match]; directory listing of dirdev. opt match a substring",
|
||||
NULL,
|
||||
EblDirCmd
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Initialize the commands in this in this file
|
||||
**/
|
||||
VOID
|
||||
EblInitializeDirCmd (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (FeaturePcdGet (PcdEmbeddedDirCmd)) {
|
||||
EblAddCommands (mCmdDirTemplate, sizeof (mCmdDirTemplate)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
}
|
||||
|
194
EmbeddedPkg/Ebl/Ebl.h
Normal file
194
EmbeddedPkg/Ebl/Ebl.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/** @file
|
||||
Include flie for basic command line parser for EBL (Embedded Boot Loader)
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
|
||||
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __EBL_H__
|
||||
#define __EBL_H__
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/SimpleFileSystem.h>
|
||||
#include <Protocol/FirmwareVolume2.h>
|
||||
#include <Protocol/LoadFile.h>
|
||||
#include <Protocol/FirmwareVolumeBlock.h>
|
||||
#include <Protocol/PxeBaseCode.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Protocol/EblAddCommand.h>
|
||||
#include <Protocol/PciIo.h>
|
||||
#include <Protocol/DevicePath.h>
|
||||
|
||||
#include <Guid/FileInfo.h>
|
||||
#include <Guid/DxeServices.h>
|
||||
#include <Guid/MemoryTypeInformation.h>
|
||||
#include <Guid/MemoryAllocationHob.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/EfiFileLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/EblCmdLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/EblNetworkLib.h>
|
||||
|
||||
#include <IndustryStandard/Pci.h>
|
||||
|
||||
//
|
||||
// Prompt for the command line
|
||||
//
|
||||
#define CMD_SEPERATOR ';'
|
||||
#define EBL_MAX_COMMAND_COUNT 0x100
|
||||
#define MAX_CMD_HISTORY 16
|
||||
#define MAX_CMD_LINE 256
|
||||
#define MAX_ARGS 32
|
||||
|
||||
#define EBL_CR 0x0a
|
||||
#define EBL_LF 0x0d
|
||||
|
||||
#define EFI_SET_TIMER_TO_SECOND 10000000
|
||||
|
||||
|
||||
|
||||
EBL_COMMAND_TABLE *
|
||||
EblGetCommand (
|
||||
IN CHAR8 *CommandName
|
||||
);
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EblPathToDevice (
|
||||
IN CHAR8 *Path,
|
||||
OUT EFI_HANDLE *DeviceHandle,
|
||||
OUT EFI_DEVICE_PATH_PROTOCOL **PathDevicePath,
|
||||
OUT VOID **Buffer,
|
||||
OUT UINTN *BufferSize
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
EblAnyKeyToContinueQtoQuit (
|
||||
IN UINTN *CurrentRow,
|
||||
IN BOOLEAN PrefixNewline
|
||||
);
|
||||
|
||||
VOID
|
||||
EblUpdateDeviceLists (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EblInitializeCmdTable (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EblShutdownExternalCmdTable (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EblSetTextColor (
|
||||
UINTN Attribute
|
||||
);
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
EblGetCharKey (
|
||||
IN OUT EFI_INPUT_KEY *Key,
|
||||
IN UINTN TimoutInSec,
|
||||
IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL
|
||||
);
|
||||
|
||||
// BugBug: Move me to a library
|
||||
INTN
|
||||
EFIAPI
|
||||
AsciiStrniCmp (
|
||||
IN CONST CHAR8 *FirstString,
|
||||
IN CONST CHAR8 *SecondString,
|
||||
IN UINTN Length
|
||||
);
|
||||
|
||||
|
||||
VOID
|
||||
EblInitializeDeviceCmd (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EblInitializemdHwDebugCmds (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EblInitializeDirCmd (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EblInitializeHobCmd (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EblInitializemdHwIoDebugCmds (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EblInitializeScriptCmd (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EblInitializeNetworkCmd (
|
||||
VOID
|
||||
);
|
||||
|
||||
CHAR8 *
|
||||
ParseArguments (
|
||||
IN CHAR8 *CmdLine,
|
||||
OUT UINTN *Argc,
|
||||
OUT CHAR8 **Argv
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
ProcessCmdLine (
|
||||
IN CHAR8 *CmdLine,
|
||||
IN UINTN MaxCmdLineSize
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
OutputData (
|
||||
IN UINT8 *Address,
|
||||
IN UINTN Length,
|
||||
IN UINTN Width,
|
||||
IN UINTN Offset
|
||||
);
|
||||
|
||||
extern UINTN gScreenColumns;
|
||||
extern UINTN gScreenRows;
|
||||
extern BOOLEAN gPageBreak;
|
||||
extern CHAR8 *gMemMapType[];
|
||||
|
||||
#endif
|
||||
|
110
EmbeddedPkg/Ebl/Ebl.inf
Normal file
110
EmbeddedPkg/Ebl/Ebl.inf
Normal file
@@ -0,0 +1,110 @@
|
||||
#%HEADER%
|
||||
#/** @file
|
||||
# EBL Applicaiton
|
||||
#
|
||||
# This is a shell application that will display Hello World.
|
||||
# Copyright (c) 2007, Intel Corporation.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Defines Section - statements that will be processed to create a Makefile.
|
||||
#
|
||||
################################################################################
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = Ebl
|
||||
FILE_GUID = 3CEF354A-3B7A-4519-AD70-72A134698311
|
||||
MODULE_TYPE = UEFI_APPLICATION
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = EdkBootLoaderEntry
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
[Sources.common]
|
||||
Main.c
|
||||
Command.c
|
||||
EfiDevice.c
|
||||
HwDebug.c
|
||||
HwIoDebug.c
|
||||
Dir.c
|
||||
Hob.c
|
||||
Script.c
|
||||
Ebl.h
|
||||
Network.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
IntelFrameworkPkg/IntelFrameworkPkg.dec
|
||||
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
DebugLib
|
||||
UefiLib
|
||||
UefiApplicationEntryPoint
|
||||
UefiBootServicesTableLib
|
||||
UefiRuntimeServicesTableLib
|
||||
BaseMemoryLib
|
||||
MemoryAllocationLib
|
||||
DevicePathLib
|
||||
IoLib
|
||||
PrintLib
|
||||
PcdLib
|
||||
EfiFileLib
|
||||
HobLib
|
||||
BaseLib
|
||||
EblCmdLib
|
||||
EblNetworkLib
|
||||
|
||||
[LibraryClasses.ARM]
|
||||
SemihostLib
|
||||
|
||||
[Protocols.common]
|
||||
gEfiFirmwareVolume2ProtocolGuid
|
||||
gEfiFirmwareVolumeBlockProtocolGuid
|
||||
gEfiBlockIoProtocolGuid
|
||||
gEfiSimpleFileSystemProtocolGuid
|
||||
gEfiLoadFileProtocolGuid
|
||||
gEfiLoadedImageProtocolGuid
|
||||
gEfiPxeBaseCodeProtocolGuid
|
||||
gEfiEblAddCommandProtocolGuid
|
||||
gEfiDiskIoProtocolGuid
|
||||
gEfiPciIoProtocolGuid
|
||||
gEfiSimpleNetworkProtocolGuid
|
||||
|
||||
[Guids.common]
|
||||
gEfiDxeServicesTableGuid
|
||||
gEfiFileInfoGuid
|
||||
gEfiHobMemoryAllocModuleGuid
|
||||
gEfiMemoryTypeInformationGuid
|
||||
|
||||
[FeaturePcd.common]
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd
|
||||
|
||||
[FixedPcd.common]
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedShellCharacterEcho
|
||||
gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt
|
||||
|
969
EmbeddedPkg/Ebl/EfiDevice.c
Normal file
969
EmbeddedPkg/Ebl/EfiDevice.c
Normal file
@@ -0,0 +1,969 @@
|
||||
/** @file
|
||||
EBL commands for EFI and PI Devices
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
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"
|
||||
|
||||
|
||||
EFI_DXE_SERVICES *gDS = NULL;
|
||||
|
||||
|
||||
/**
|
||||
Print information about the File System device.
|
||||
|
||||
@param File Open File for the device
|
||||
|
||||
**/
|
||||
VOID
|
||||
EblPrintFsInfo (
|
||||
IN EFI_OPEN_FILE *File
|
||||
)
|
||||
{
|
||||
if (File == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiPrint (" %a: ", File->DeviceName);
|
||||
if (File->FsInfo != NULL) {
|
||||
AsciiPrint ("%s: ", File->FsInfo->VolumeLabel);
|
||||
if (File->FsInfo->ReadOnly) {
|
||||
AsciiPrint ("ReadOnly");
|
||||
}
|
||||
}
|
||||
|
||||
AsciiPrint ("\n");
|
||||
EfiClose (File);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Print information about the FV devices.
|
||||
|
||||
@param File Open File for the device
|
||||
|
||||
**/
|
||||
VOID
|
||||
EblPrintFvbInfo (
|
||||
IN EFI_OPEN_FILE *File
|
||||
)
|
||||
{
|
||||
if (File == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiPrint (" %a: 0x%08lx - 0x%08lx : 0x%08x\n", File->DeviceName, File->FvStart, File->FvStart + File->FvSize - 1, File->FvSize);
|
||||
EfiClose (File);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Print information about the Blk IO devices.
|
||||
If the device supports PXE dump out extra information
|
||||
|
||||
@param File Open File for the device
|
||||
|
||||
**/
|
||||
VOID
|
||||
EblPrintBlkIoInfo (
|
||||
IN EFI_OPEN_FILE *File
|
||||
)
|
||||
{
|
||||
UINT64 DeviceSize;
|
||||
|
||||
|
||||
if (File == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiPrint (" %a: ", File->DeviceName);
|
||||
if (File->FsBlockIoMedia.RemovableMedia) {
|
||||
AsciiPrint ("Removable ");
|
||||
}
|
||||
if (!File->FsBlockIoMedia.MediaPresent) {
|
||||
AsciiPrint ("No Media ");
|
||||
}
|
||||
if (File->FsBlockIoMedia.LogicalPartition) {
|
||||
AsciiPrint ("Partition ");
|
||||
}
|
||||
DeviceSize = MultU64x32 (File->FsBlockIoMedia.LastBlock + 1, File->FsBlockIoMedia.BlockSize);
|
||||
AsciiPrint ("Size = 0x%lX\n", DeviceSize);
|
||||
|
||||
EfiClose (File);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Print information about the Load File devices.
|
||||
If the device supports PXE dump out extra information
|
||||
|
||||
@param File Open File for the device
|
||||
|
||||
**/
|
||||
VOID
|
||||
EblPrintLoadFileInfo (
|
||||
IN EFI_OPEN_FILE *File
|
||||
)
|
||||
{
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
|
||||
MAC_ADDR_DEVICE_PATH *MacAddr;
|
||||
UINTN HwAddressSize;
|
||||
UINTN Index;
|
||||
|
||||
if (File == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiPrint (" %a: %a ", File->DeviceName, EblLoadFileBootTypeString (File->EfiHandle));
|
||||
|
||||
if (File->DevicePath != NULL) {
|
||||
// Try to print out the MAC address
|
||||
for (DevicePathNode = File->DevicePath;
|
||||
!IsDevicePathEnd (DevicePathNode);
|
||||
DevicePathNode = NextDevicePathNode (DevicePathNode)) {
|
||||
|
||||
if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePathNode) == MSG_MAC_ADDR_DP)) {
|
||||
MacAddr = (MAC_ADDR_DEVICE_PATH *)DevicePathNode;
|
||||
|
||||
HwAddressSize = sizeof (EFI_MAC_ADDRESS);
|
||||
if (MacAddr->IfType == 0x01 || MacAddr->IfType == 0x00) {
|
||||
HwAddressSize = 6;
|
||||
}
|
||||
|
||||
AsciiPrint ("MAC ");
|
||||
for (Index = 0; Index < HwAddressSize; Index++) {
|
||||
AsciiPrint ("%02x", MacAddr->MacAddress.Addr[Index] & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsciiPrint ("\n");
|
||||
EfiClose (File);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Dump information about devices in the system.
|
||||
|
||||
fv: PI Firmware Volume
|
||||
fs: EFI Simple File System
|
||||
blk: EFI Block IO
|
||||
LoadFile: EFI Load File Protocol (commonly PXE network boot)
|
||||
|
||||
Argv[0] - "device"
|
||||
|
||||
@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
|
||||
EblDeviceCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINTN CurrentRow;
|
||||
UINTN Max;
|
||||
|
||||
CurrentRow = 0;
|
||||
|
||||
// Need to call here to make sure Device Counts are valid
|
||||
EblUpdateDeviceLists ();
|
||||
|
||||
Max = EfiGetDeviceCounts (EfiOpenFirmwareVolume);
|
||||
if (Max != 0) {
|
||||
AsciiPrint ("Firmware Volume Devices:\n");
|
||||
for (Index = 0; Index < Max; Index++) {
|
||||
EblPrintFvbInfo (EfiDeviceOpenByType (EfiOpenFirmwareVolume, Index));
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Max = EfiGetDeviceCounts (EfiOpenFileSystem);
|
||||
if (Max != 0) {
|
||||
AsciiPrint ("File System Devices:\n");
|
||||
for (Index = 0; Index < Max; Index++) {
|
||||
EblPrintFsInfo (EfiDeviceOpenByType (EfiOpenFileSystem, Index));
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Max = EfiGetDeviceCounts (EfiOpenBlockIo);
|
||||
if (Max != 0) {
|
||||
AsciiPrint ("Block IO Devices:\n");
|
||||
for (Index = 0; Index < Max; Index++) {
|
||||
EblPrintBlkIoInfo (EfiDeviceOpenByType (EfiOpenBlockIo, Index));
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Max = EfiGetDeviceCounts (EfiOpenLoadFile);
|
||||
if (Max != 0) {
|
||||
AsciiPrint ("LoadFile Devices: (usually network)\n");
|
||||
for (Index = 0; Index < Max; Index++) {
|
||||
EblPrintLoadFileInfo (EfiDeviceOpenByType (EfiOpenLoadFile, Index));
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start an EFI image (PE32+ with EFI defined entry point).
|
||||
|
||||
Argv[0] - "start"
|
||||
Argv[1] - device name and path
|
||||
Argv[2] - "" string to pass into image being started
|
||||
|
||||
start fs1:\Temp\Fv.Fv "arg to pass" ; load an FV from the disk and pass the
|
||||
; ascii string arg to pass to the image
|
||||
start fv0:\FV ; load an FV from an FV (not common)
|
||||
start LoadFile0: ; load an FV via a PXE boot
|
||||
|
||||
@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
|
||||
EblStartCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_OPEN_FILE *File;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
EFI_HANDLE ImageHandle;
|
||||
UINTN ExitDataSize;
|
||||
CHAR16 *ExitData;
|
||||
VOID *Buffer;
|
||||
UINTN BufferSize;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
|
||||
|
||||
ImageHandle = NULL;
|
||||
|
||||
if (Argc < 2) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
DevicePath = File->DevicePath;
|
||||
if (DevicePath != NULL) {
|
||||
// check for device path form: blk, fv, fs, and loadfile
|
||||
Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, NULL, 0, &ImageHandle);
|
||||
} else {
|
||||
// Check for buffer form: A0x12345678:0x1234 syntax.
|
||||
// Means load using buffer starting at 0x12345678 of size 0x1234.
|
||||
|
||||
Status = EfiReadAllocatePool (File, &Buffer, &BufferSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
EfiClose (File);
|
||||
return Status;
|
||||
}
|
||||
Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, Buffer, BufferSize, &ImageHandle);
|
||||
|
||||
FreePool (Buffer);
|
||||
}
|
||||
|
||||
EfiClose (File);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
if (Argc >= 3) {
|
||||
// Argv[2] is a "" string that we pass directly to the EFI application without the ""
|
||||
// We don't pass Argv[0] to the EFI Application (it's name) just the args
|
||||
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
ImageInfo->LoadOptionsSize = (UINT32)AsciiStrSize (Argv[2]);
|
||||
ImageInfo->LoadOptions = AllocatePool (ImageInfo->LoadOptionsSize);
|
||||
AsciiStrCpy (ImageInfo->LoadOptions, Argv[2]);
|
||||
}
|
||||
|
||||
// Transfer control to the EFI image we loaded with LoadImage()
|
||||
Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Load a Firmware Volume (FV) into memory from a device. This causes drivers in
|
||||
the FV to be dispatched if the dependancies of the drivers are met.
|
||||
|
||||
Argv[0] - "loadfv"
|
||||
Argv[1] - device name and path
|
||||
|
||||
loadfv fs1:\Temp\Fv.Fv ; load an FV from the disk
|
||||
loadfv fv0:\FV ; load an FV from an FV (not common)
|
||||
loadfv LoadFile0: ; load an FV via a PXE boot
|
||||
|
||||
@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
|
||||
EblLoadFvCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_OPEN_FILE *File;
|
||||
VOID *FvStart;
|
||||
UINTN FvSize;
|
||||
EFI_HANDLE FvHandle;
|
||||
|
||||
|
||||
if (Argc < 2) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (File->Type == EfiOpenMemoryBuffer) {
|
||||
// If it is a address just use it.
|
||||
Status = gDS->ProcessFirmwareVolume (File->Buffer, File->Size, &FvHandle);
|
||||
} else {
|
||||
// If it is a file read it into memory and use it
|
||||
Status = EfiReadAllocatePool (File, &FvStart, &FvSize);
|
||||
EfiClose (File);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gDS->ProcessFirmwareVolume (FvStart, FvSize, &FvHandle);
|
||||
FreePool (FvStart);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Perform an EFI connect to connect devices that follow the EFI driver model.
|
||||
If it is a PI system also call the dispatcher in case a new FV was made
|
||||
availible by one of the connect EFI drivers (this is not a common case).
|
||||
|
||||
Argv[0] - "connect"
|
||||
|
||||
@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
|
||||
EblConnectCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN HandleCount;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
UINTN Index;
|
||||
BOOLEAN Dispatch;
|
||||
EFI_OPEN_FILE *File;
|
||||
|
||||
|
||||
if (Argc > 1) {
|
||||
if ((*Argv[1] == 'd') || (*Argv[1] == 'D')) {
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
AllHandles,
|
||||
NULL,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < HandleCount; Index++) {
|
||||
gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// Given we disconnect our console we should go and do a connect now
|
||||
//
|
||||
} else {
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File != NULL) {
|
||||
AsciiPrint ("Connecting %a\n", Argv[1]);
|
||||
gBS->ConnectController (File->EfiHandle, NULL, NULL, TRUE);
|
||||
EfiClose (File);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dispatch = FALSE;
|
||||
do {
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
AllHandles,
|
||||
NULL,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < HandleCount; Index++) {
|
||||
gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
|
||||
}
|
||||
|
||||
FreePool (HandleBuffer);
|
||||
|
||||
//
|
||||
// Check to see if it's possible to dispatch an more DXE drivers.
|
||||
// The BdsLibConnectAllEfi () may have made new DXE drivers show up.
|
||||
// If anything is Dispatched Status == EFI_SUCCESS and we will try
|
||||
// the connect again.
|
||||
//
|
||||
if (gDS == NULL) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
} else {
|
||||
Status = gDS->Dispatch ();
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Dispatch = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
} while (!EFI_ERROR (Status));
|
||||
|
||||
if (Dispatch) {
|
||||
AsciiPrint ("Connected and dispatched\n");
|
||||
} else {
|
||||
AsciiPrint ("Connect\n");
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CHAR8 *gMemMapType[] = {
|
||||
"reserved ",
|
||||
"LoaderCode",
|
||||
"LoaderData",
|
||||
"BS_code ",
|
||||
"BS_data ",
|
||||
"RT_code ",
|
||||
"RT_data ",
|
||||
"available ",
|
||||
"Unusable ",
|
||||
"ACPI_recl ",
|
||||
"ACPI_NVS ",
|
||||
"MemMapIO ",
|
||||
"MemPortIO ",
|
||||
"PAL_code "
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Dump out the EFI memory map
|
||||
|
||||
Argv[0] - "memmap"
|
||||
|
||||
@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
|
||||
EblMemMapCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_MEMORY_DESCRIPTOR *MemMap;
|
||||
EFI_MEMORY_DESCRIPTOR *OrigMemMap;
|
||||
UINTN MemMapSize;
|
||||
UINTN MapKey;
|
||||
UINTN DescriptorSize;
|
||||
UINT32 DescriptorVersion;
|
||||
UINT64 PageCount[EfiMaxMemoryType];
|
||||
UINTN Index;
|
||||
UINT64 EntrySize;
|
||||
UINTN CurrentRow;
|
||||
UINT64 TotalMemory;
|
||||
|
||||
ZeroMem (PageCount, sizeof (PageCount));
|
||||
|
||||
AsciiPrint ("EFI Memory Map\n");
|
||||
|
||||
// First call is to figure out how big the buffer needs to be
|
||||
MemMapSize = 0;
|
||||
MemMap = NULL;
|
||||
Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
// In case the AllocatPool changes the memory map we added in some extra descriptors
|
||||
MemMapSize += (DescriptorSize * 0x100);
|
||||
OrigMemMap = MemMap = AllocatePool (MemMapSize);
|
||||
if (OrigMemMap != NULL) {
|
||||
// 2nd time we get the data
|
||||
Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
for (Index = 0, CurrentRow = 0; Index < MemMapSize/DescriptorSize; Index++) {
|
||||
EntrySize = LShiftU64 (MemMap->NumberOfPages, 12);
|
||||
AsciiPrint ("\n%a %016lx - %016lx: # %08lx %016lx", gMemMapType[MemMap->Type % EfiMaxMemoryType], MemMap->PhysicalStart, MemMap->PhysicalStart + EntrySize -1, MemMap->NumberOfPages, MemMap->Attribute);
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
PageCount[MemMap->Type % EfiMaxMemoryType] += MemMap->NumberOfPages;
|
||||
MemMap = NEXT_MEMORY_DESCRIPTOR (MemMap, DescriptorSize);
|
||||
}
|
||||
}
|
||||
|
||||
for (Index = 0, TotalMemory = 0; Index < EfiMaxMemoryType; Index++) {
|
||||
if (PageCount[Index] != 0) {
|
||||
AsciiPrint ("\n %a %,7ld Pages (%,14ld)", gMemMapType[Index], PageCount[Index], LShiftU64 (PageCount[Index], 12));
|
||||
if (Index == EfiLoaderCode ||
|
||||
Index == EfiLoaderData ||
|
||||
Index == EfiBootServicesCode ||
|
||||
Index == EfiBootServicesData ||
|
||||
Index == EfiRuntimeServicesCode ||
|
||||
Index == EfiRuntimeServicesData ||
|
||||
Index == EfiConventionalMemory ||
|
||||
Index == EfiACPIReclaimMemory ||
|
||||
Index == EfiACPIMemoryNVS ||
|
||||
Index == EfiPalCode
|
||||
) {
|
||||
// Count total memory
|
||||
TotalMemory += PageCount[Index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsciiPrint ("\nTotal Memory: %,ld MB (%,ld bytes)\n", RShiftU64 (TotalMemory, 8), LShiftU64 (TotalMemory, 12));
|
||||
|
||||
FreePool (OrigMemMap);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Load a file into memory and optionally jump to it. A load addres can be
|
||||
specified or automatically allocated. A quoted command line can optionally
|
||||
be passed into the image.
|
||||
|
||||
Argv[0] - "go"
|
||||
Argv[1] - Device Name:path for the file to load
|
||||
Argv[2] - Address to load to or '*' if the load address will be allocated
|
||||
Argv[3] - Optional Entry point to the image. Image will be called if present
|
||||
Argv[4] - "" string that will be passed as Argc & Argv to EntryPoint. Needs
|
||||
to include the command name
|
||||
|
||||
go fv1:\EblCmdX 0x10000 0x10010 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX
|
||||
from FV1 to location 0x10000 and call the entry point at 0x10010 passing
|
||||
in "EblCmdX Arg2 Arg3 Arg4" as the arguments.
|
||||
|
||||
go fv0:\EblCmdX * 0x10 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX from FS0
|
||||
to location allocated by this comamnd and call the entry point at offset 0x10
|
||||
passing in "EblCmdX Arg2 Arg3 Arg4" as the arguments.
|
||||
|
||||
go fv1:\EblCmdX 0x10000; Load EblCmdX to address 0x10000 and return
|
||||
|
||||
@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
|
||||
EblGoCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_OPEN_FILE *File;
|
||||
VOID *Address;
|
||||
UINTN Size;
|
||||
EBL_COMMMAND EntryPoint;
|
||||
UINTN EntryPointArgc;
|
||||
CHAR8 *EntryPointArgv[MAX_ARGS];
|
||||
|
||||
|
||||
if (Argc <= 2) {
|
||||
// device name and laod address are required
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File == NULL) {
|
||||
AsciiPrint (" %a is not a valid path\n", Argv[1]);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EntryPoint = (EBL_COMMMAND)((Argc > 3) ? (UINTN)AsciiStrHexToUintn (Argv[3]) : (UINTN)NULL);
|
||||
if (Argv[2][0] == '*') {
|
||||
// * Means allocate the buffer
|
||||
Status = EfiReadAllocatePool (File, &Address, &Size);
|
||||
|
||||
// EntryPoint is relatvie to the start of the image
|
||||
EntryPoint = (EBL_COMMMAND)((UINTN)EntryPoint + (UINTN)Address);
|
||||
|
||||
} else {
|
||||
Address = (VOID *)AsciiStrHexToUintn (Argv[2]);
|
||||
Size = File->Size;
|
||||
|
||||
// File->Size for LoadFile is lazy so we need to use the tell to figure it out
|
||||
EfiTell (File, NULL);
|
||||
Status = EfiRead (File, Address, &Size);
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
AsciiPrint ("Loaded %,d bytes to 0x%08x\n", Size, Address);
|
||||
|
||||
if (Argc > 3) {
|
||||
if (Argc > 4) {
|
||||
ParseArguments (Argv[4], &EntryPointArgc, EntryPointArgv);
|
||||
} else {
|
||||
EntryPointArgc = 1;
|
||||
EntryPointArgv[0] = File->FileName;
|
||||
}
|
||||
|
||||
Status = EntryPoint (EntryPointArgc, EntryPointArgv);
|
||||
}
|
||||
}
|
||||
|
||||
EfiClose (File);
|
||||
return Status;
|
||||
}
|
||||
|
||||
#define FILE_COPY_CHUNK 0x20000
|
||||
|
||||
EFI_STATUS
|
||||
EblFileCopyCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_OPEN_FILE *Source = NULL;
|
||||
EFI_OPEN_FILE *Destination = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
VOID *Buffer = NULL;
|
||||
UINTN Size;
|
||||
UINTN Offset;
|
||||
UINTN Chunk = FILE_COPY_CHUNK;
|
||||
|
||||
if (Argc < 3) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Source = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (Source == NULL) {
|
||||
AsciiPrint("Source file open error.\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Destination = EfiOpen(Argv[2], EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
|
||||
if (Destination == NULL) {
|
||||
AsciiPrint("Destination file open error.\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Buffer = AllocatePool(FILE_COPY_CHUNK);
|
||||
if (Buffer == NULL) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Size = EfiTell(Source, NULL);
|
||||
|
||||
for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size; Offset += Chunk) {
|
||||
Chunk = FILE_COPY_CHUNK;
|
||||
|
||||
Status = EfiRead(Source, Buffer, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Read file error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EfiWrite(Destination, Buffer, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Write file error\n");
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Any left over?
|
||||
if (Offset < Size) {
|
||||
Chunk = Size - Offset;
|
||||
|
||||
Status = EfiRead(Source, Buffer, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Read file error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EfiWrite(Destination, Buffer, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Write file error\n");
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (Source != NULL) {
|
||||
Status = EfiClose(Source);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Source close error %r\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (Destination != NULL) {
|
||||
Status = EfiClose(Destination);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Destination close error %r\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (Buffer != NULL) {
|
||||
FreePool(Buffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EblFileDiffCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_OPEN_FILE *File1 = NULL;
|
||||
EFI_OPEN_FILE *File2 = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
VOID *Buffer1 = NULL;
|
||||
VOID *Buffer2 = NULL;
|
||||
UINTN Size1;
|
||||
UINTN Size2;
|
||||
UINTN Offset;
|
||||
UINTN Chunk = FILE_COPY_CHUNK;
|
||||
|
||||
if (Argc != 3) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
File1 = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File1 == NULL) {
|
||||
AsciiPrint("File 1 open error.\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
File2 = EfiOpen(Argv[2], EFI_FILE_MODE_READ, 0);
|
||||
if (File2 == NULL) {
|
||||
AsciiPrint("File 2 open error.\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Size1 = EfiTell(File1, NULL);
|
||||
Size2 = EfiTell(File2, NULL);
|
||||
|
||||
if (Size1 != Size2) {
|
||||
AsciiPrint("Files differ.\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Buffer1 = AllocatePool(FILE_COPY_CHUNK);
|
||||
if (Buffer1 == NULL) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Buffer2 = AllocatePool(FILE_COPY_CHUNK);
|
||||
if (Buffer2 == NULL) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size1; Offset += Chunk) {
|
||||
Chunk = FILE_COPY_CHUNK;
|
||||
|
||||
Status = EfiRead(File1, Buffer1, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 1 read error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EfiRead(File2, Buffer2, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 2 read error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (CompareMem(Buffer1, Buffer2, Chunk) != 0) {
|
||||
AsciiPrint("Files differ.\n");
|
||||
goto Exit;
|
||||
};
|
||||
}
|
||||
|
||||
// Any left over?
|
||||
if (Offset < Size1) {
|
||||
Chunk = Size1 - Offset;
|
||||
|
||||
Status = EfiRead(File1, Buffer1, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 1 read error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EfiRead(File2, Buffer2, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 2 read error\n");
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (CompareMem(Buffer1, Buffer2, Chunk) != 0) {
|
||||
AsciiPrint("Files differ.\n");
|
||||
} else {
|
||||
AsciiPrint("Files are identical.\n");
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (File1 != NULL) {
|
||||
Status = EfiClose(File1);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 1 close error %r\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (File2 != NULL) {
|
||||
Status = EfiClose(File2);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 2 close error %r\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (Buffer1 != NULL) {
|
||||
FreePool(Buffer1);
|
||||
}
|
||||
|
||||
if (Buffer2 != NULL) {
|
||||
FreePool(Buffer2);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDeviceTemplate[] =
|
||||
{
|
||||
{
|
||||
"connect",
|
||||
"[d]; Connect all EFI devices. d means disconnect",
|
||||
NULL,
|
||||
EblConnectCmd
|
||||
},
|
||||
{
|
||||
"device",
|
||||
"; Show information about boot devices",
|
||||
NULL,
|
||||
EblDeviceCmd
|
||||
},
|
||||
{
|
||||
"go",
|
||||
" dev:path loadaddress entrypoint args; load to given address and jump in",
|
||||
NULL,
|
||||
EblGoCmd
|
||||
},
|
||||
{
|
||||
"loadfv",
|
||||
" devname; Load PI FV from device",
|
||||
NULL,
|
||||
EblLoadFvCmd
|
||||
},
|
||||
{
|
||||
"start",
|
||||
" path; EFI Boot Device:filepath. fs1:\\EFI\\BOOT.EFI",
|
||||
NULL,
|
||||
EblStartCmd
|
||||
},
|
||||
{
|
||||
"memmap",
|
||||
"; dump EFI memory map",
|
||||
NULL,
|
||||
EblMemMapCmd
|
||||
},
|
||||
{
|
||||
"cp",
|
||||
" file1 file2; copy file",
|
||||
NULL,
|
||||
EblFileCopyCmd
|
||||
},
|
||||
{
|
||||
"diff",
|
||||
" file1 file2; compare files",
|
||||
NULL,
|
||||
EblFileDiffCmd
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Initialize the commands in this in this file
|
||||
**/
|
||||
|
||||
VOID
|
||||
EblInitializeDeviceCmd (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS);
|
||||
EblAddCommands (mCmdDeviceTemplate, sizeof (mCmdDeviceTemplate)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
|
232
EmbeddedPkg/Ebl/Hob.c
Normal file
232
EmbeddedPkg/Ebl/Hob.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/** @file
|
||||
Hob command for EBL (Embedded Boot Loader)
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
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.
|
||||
|
||||
Module Name: Hob.c
|
||||
|
||||
Search/Replace Dir with the name of your new command
|
||||
|
||||
Boot Mode:
|
||||
==========
|
||||
BOOT_WITH_FULL_CONFIGURATION 0x00
|
||||
BOOT_WITH_MINIMAL_CONFIGURATION 0x01
|
||||
BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02
|
||||
BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS 0x03
|
||||
BOOT_WITH_DEFAULT_SETTINGS 0x04
|
||||
BOOT_ON_S4_RESUME 0x05
|
||||
BOOT_ON_S5_RESUME 0x06
|
||||
BOOT_ON_S2_RESUME 0x10
|
||||
BOOT_ON_S3_RESUME 0x11
|
||||
BOOT_ON_FLASH_UPDATE 0x12
|
||||
BOOT_IN_RECOVERY_MODE 0x20
|
||||
BOOT_IN_RECOVERY_MODE_MASK 0x40
|
||||
BOOT_SPECIAL_MASK 0x80
|
||||
|
||||
Mem Alloc HOB Type:
|
||||
===================
|
||||
typedef enum {
|
||||
EfiReservedMemoryType = 0x00
|
||||
EfiLoaderCode = 0x01
|
||||
EfiLoaderData = 0x02
|
||||
EfiBootServicesCode = 0x03
|
||||
EfiBootServicesData = 0x04
|
||||
EfiRuntimeServicesCode = 0x05
|
||||
EfiRuntimeServicesData = 0x06
|
||||
EfiConventionalMemory = 0x07
|
||||
EfiUnusableMemory = 0x08
|
||||
EfiACPIReclaimMemory = 0x09
|
||||
EfiACPIMemoryNVS = 0x0a
|
||||
EfiMemoryMappedIO = 0x0b
|
||||
EfiMemoryMappedIOPortSpace = 0x0c
|
||||
EfiPalCode = 0x0d
|
||||
EfiMaxMemoryType = 0x0e
|
||||
} EFI_MEMORY_TYPE;
|
||||
|
||||
Resource Hob Tye:
|
||||
=================
|
||||
EFI_RESOURCE_SYSTEM_MEMORY 0
|
||||
EFI_RESOURCE_MEMORY_MAPPED_IO 1
|
||||
EFI_RESOURCE_IO 2
|
||||
EFI_RESOURCE_FIRMWARE_DEVICE 3
|
||||
EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 4
|
||||
EFI_RESOURCE_MEMORY_RESERVED 5
|
||||
EFI_RESOURCE_IO_RESERVED 6
|
||||
EFI_RESOURCE_MAX_MEMORY_TYPE 7
|
||||
|
||||
Resource Hob Attribute (last thing printed):
|
||||
============================================
|
||||
EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001
|
||||
EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002
|
||||
EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004
|
||||
EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008
|
||||
EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010
|
||||
EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020
|
||||
EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040
|
||||
EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080
|
||||
EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100
|
||||
EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200
|
||||
EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400
|
||||
EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800
|
||||
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000
|
||||
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000
|
||||
EFI_RESOURCE_ATTRIBUTE_16_BIT_IO 0x00004000
|
||||
EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000
|
||||
EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000
|
||||
EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000
|
||||
|
||||
**/
|
||||
|
||||
#include "Ebl.h"
|
||||
// BugBug: Autogen does not allow this to be included currently
|
||||
//#include <EdkModulePkg/Include/EdkDxe.h>
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED char *mHobResourceType[] = {
|
||||
"Memory ",
|
||||
"MMIO ",
|
||||
"IO ",
|
||||
"Firmware ",
|
||||
"MMIO Port ",
|
||||
"Reserved ",
|
||||
"IO Reserved",
|
||||
"Illegal "
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Dump out the HOBs in the system. HOBs are defined in the PI specificaiton
|
||||
and they are used to hand off information from PEI to DXE.
|
||||
|
||||
Argv[0] - "hob"
|
||||
|
||||
@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
|
||||
EblHobCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
UINTN CurrentRow;
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;
|
||||
UINTN Index;
|
||||
|
||||
CurrentRow = 0;
|
||||
for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
|
||||
if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
|
||||
AsciiPrint ("PHIT HOB Ver %x Boot Mode %02x Top %lx Bottom %lx\n",
|
||||
Hob.HandoffInformationTable->Version,
|
||||
Hob.HandoffInformationTable->BootMode,
|
||||
Hob.HandoffInformationTable->EfiMemoryTop,
|
||||
Hob.HandoffInformationTable->EfiMemoryBottom
|
||||
);
|
||||
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
AsciiPrint (" Free Top %lx Free Bottom %lx End Of HOB %lx\n",
|
||||
Hob.HandoffInformationTable->EfiFreeMemoryTop,
|
||||
Hob.HandoffInformationTable->EfiFreeMemoryBottom,
|
||||
Hob.HandoffInformationTable->EfiEndOfHobList
|
||||
);
|
||||
|
||||
} else if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
|
||||
// mod(%) on array index is just to prevent buffer overrun
|
||||
AsciiPrint ("Mem Alloc HOB %a %g %08lx:%lx\n",
|
||||
(Hob.MemoryAllocation->AllocDescriptor.MemoryType < EfiMaxMemoryType) ? gMemMapType[Hob.MemoryAllocation->AllocDescriptor.MemoryType] : "ILLEGAL TYPE",
|
||||
&Hob.MemoryAllocation->AllocDescriptor.Name,
|
||||
Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress,
|
||||
Hob.MemoryAllocation->AllocDescriptor.MemoryLength
|
||||
);
|
||||
if (CompareGuid (&gEfiHobMemoryAllocModuleGuid, &Hob.MemoryAllocation->AllocDescriptor.Name)) {
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
AsciiPrint (" Module Name %g EntryPoint %lx\n", &Hob.MemoryAllocationModule->ModuleName, Hob.MemoryAllocationModule->EntryPoint);
|
||||
}
|
||||
} else if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
|
||||
AsciiPrint ("Resource HOB %a %g %08lx:%lx\n Attributes: %08x\n",
|
||||
(Hob.ResourceDescriptor->ResourceType < EFI_RESOURCE_MAX_MEMORY_TYPE) ? mHobResourceType[Hob.ResourceDescriptor->ResourceType] : mHobResourceType[EFI_RESOURCE_MAX_MEMORY_TYPE],
|
||||
&Hob.ResourceDescriptor->Owner,
|
||||
Hob.ResourceDescriptor->PhysicalStart,
|
||||
Hob.ResourceDescriptor->ResourceLength,
|
||||
Hob.ResourceDescriptor->ResourceAttribute
|
||||
);
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
} else if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
|
||||
AsciiPrint ("GUID HOB %g\n", &Hob.Guid->Name);
|
||||
if (CompareGuid (&gEfiMemoryTypeInformationGuid, &Hob.Guid->Name)) {
|
||||
EfiMemoryTypeInformation = GET_GUID_HOB_DATA (Hob.Guid);
|
||||
for (Index = 0; Index < (GET_GUID_HOB_DATA_SIZE (Hob.Guid)/sizeof (EFI_MEMORY_TYPE_INFORMATION)); Index++, EfiMemoryTypeInformation++) {
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
AsciiPrint (" %a 0x%08x\n",
|
||||
(EfiMemoryTypeInformation->Type < EfiMaxMemoryType) ? gMemMapType[EfiMemoryTypeInformation->Type] : "END ",
|
||||
EfiMemoryTypeInformation->NumberOfPages
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (Hob.Header->HobType == EFI_HOB_TYPE_FV) {
|
||||
AsciiPrint ("FV HOB %08lx:%08lx\n", Hob.FirmwareVolume->BaseAddress, Hob.FirmwareVolume->Length);
|
||||
} else if (Hob.Header->HobType == EFI_HOB_TYPE_CPU) {
|
||||
AsciiPrint ("CPU HOB: Mem %x IO %x\n", Hob.Cpu->SizeOfMemorySpace, Hob.Cpu->SizeOfIoSpace);
|
||||
} else if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_POOL) {
|
||||
AsciiPrint ("Mem Pool HOB:\n");
|
||||
/* Not in PI
|
||||
} else if (Hob.Header->HobType == EFI_HOB_TYPE_CV) {
|
||||
AsciiPrint ("CV HOB: %08lx:%08lx\n", Hob.CapsuleVolume->BaseAddress, Hob.CapsuleVolume->Length);
|
||||
*/
|
||||
}
|
||||
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHobTemplate[] =
|
||||
{
|
||||
{
|
||||
"hob",
|
||||
"; dump HOBs",
|
||||
NULL,
|
||||
EblHobCmd
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Initialize the commands in this in this file
|
||||
**/
|
||||
VOID
|
||||
EblInitializeHobCmd (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (FeaturePcdGet (PcdEmbeddedHobCmd)) {
|
||||
EblAddCommands (mCmdHobTemplate, sizeof (mCmdHobTemplate)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
}
|
||||
|
342
EmbeddedPkg/Ebl/HwDebug.c
Normal file
342
EmbeddedPkg/Ebl/HwDebug.c
Normal file
@@ -0,0 +1,342 @@
|
||||
/** @file
|
||||
Basic command line parser for EBL (Embedded Boot Loader)
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
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.
|
||||
|
||||
Module Name: HwDebug.c
|
||||
|
||||
Commands useful for debugging hardware.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ebl.h"
|
||||
|
||||
|
||||
/**
|
||||
Dump memory
|
||||
|
||||
Argv[0] - "md"
|
||||
Argv[1] - Hex Address to dump
|
||||
Argv[2] - Number of hex bytes to dump (0x20 is default)
|
||||
Argv[3] - [1|2|4|8] byte width of the dump
|
||||
|
||||
md 0x123445678 50 4 ; Dump 0x50 4 byte quantities starting at 0x123445678
|
||||
md 0x123445678 40 ; Dump 0x40 1 byte quantities starting at 0x123445678
|
||||
md 0x123445678 ; Dump 0x20 1 byte quantities starting at 0x123445678
|
||||
|
||||
@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
|
||||
EblMdCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
STATIC UINT8 *Address = NULL;
|
||||
STATIC UINTN Length = 0x20;
|
||||
STATIC UINTN Width = 1;
|
||||
|
||||
switch (Argc)
|
||||
{
|
||||
case 4:
|
||||
Width = AsciiStrHexToUintn(Argv[3]);
|
||||
case 3:
|
||||
Length = AsciiStrHexToUintn(Argv[2]);
|
||||
case 2:
|
||||
Address = (UINT8 *)AsciiStrHexToUintn(Argv[1]);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
OutputData(Address, Length, Width, (UINTN)Address);
|
||||
|
||||
Address += Length;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Fill Memory with data
|
||||
|
||||
Argv[0] - "mfill"
|
||||
Argv[1] - Hex Address to fill
|
||||
Argv[2] - Data to write (0x00 is default)
|
||||
Argv[3] - Number of units to dump.
|
||||
Argv[4] - [1|2|4|8] byte width of the dump
|
||||
|
||||
mf 0x123445678 aa 1 100 ; Start at 0x123445678 and write aa (1 byte) to the next 100 bytes
|
||||
mf 0x123445678 aa 4 100 ; Start at 0x123445678 and write aa (4 byte) to the next 400 bytes
|
||||
mf 0x123445678 aa ; Start at 0x123445678 and write aa (4 byte) to the next 1 byte
|
||||
mf 0x123445678 ; Start at 0x123445678 and write 00 (4 byte) to the next 1 byte
|
||||
|
||||
@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
|
||||
EblMfillCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
UINTN Address;
|
||||
UINTN EndAddress;
|
||||
UINT32 Data;
|
||||
UINTN Length;
|
||||
UINTN Width;
|
||||
|
||||
if (Argc < 2) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Address = AsciiStrHexToUintn (Argv[1]);
|
||||
Data = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 0;
|
||||
Width = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 4;
|
||||
Length = (Argc > 4) ? AsciiStrHexToUintn (Argv[4]) : 1;
|
||||
|
||||
for (EndAddress = Address + (Length * Width); Address < EndAddress; Address += Width) {
|
||||
if (Width == 4) {
|
||||
MmioWrite32 (Address, Data);
|
||||
} else if (Width == 2) {
|
||||
MmioWrite32 (Address, (UINT16)Data);
|
||||
} else {
|
||||
MmioWrite32 (Address, (UINT8)Data);
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Strings for PCI Class code [2]
|
||||
//
|
||||
CHAR8 *gPciDevClass[] = {
|
||||
"Old Device ",
|
||||
"Mass storage ",
|
||||
"Network ",
|
||||
"Display ",
|
||||
"Multimedia ",
|
||||
"Memory controller ",
|
||||
"Bridge device ",
|
||||
"simple communications ",
|
||||
"base system peripherals",
|
||||
"Input devices ",
|
||||
"Docking stations ",
|
||||
"Processors ",
|
||||
"serial bus ",
|
||||
};
|
||||
|
||||
|
||||
CHAR8 *gPciSerialClassCodes[] = {
|
||||
"Mass storage ",
|
||||
"Firewire ",
|
||||
"ACCESS bus ",
|
||||
"SSA ",
|
||||
"USB "
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
PCI Dump
|
||||
|
||||
Argv[0] - "pci"
|
||||
Argv[1] - bus
|
||||
Argv[2] - dev
|
||||
Argv[3] - func
|
||||
|
||||
@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
|
||||
EblPciCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_PCI_IO_PROTOCOL *Pci;
|
||||
UINTN HandleCount;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
UINTN Seg;
|
||||
UINTN Bus;
|
||||
UINTN Dev;
|
||||
UINTN Func;
|
||||
UINTN BusArg;
|
||||
UINTN DevArg;
|
||||
UINTN FuncArg;
|
||||
UINTN Index;
|
||||
UINTN Count;
|
||||
PCI_TYPE_GENERIC PciHeader;
|
||||
PCI_TYPE_GENERIC *Header;
|
||||
PCI_BRIDGE_CONTROL_REGISTER *Bridge;
|
||||
PCI_DEVICE_HEADER_TYPE_REGION *Device;
|
||||
PCI_DEVICE_INDEPENDENT_REGION *Hdr;
|
||||
CHAR8 *Str;
|
||||
UINTN ThisBus;
|
||||
|
||||
|
||||
BusArg = (Argc > 1) ? AsciiStrDecimalToUintn (Argv[1]) : 0;
|
||||
DevArg = (Argc > 2) ? AsciiStrDecimalToUintn (Argv[2]) : 0;
|
||||
FuncArg = (Argc > 3) ? AsciiStrDecimalToUintn (Argv[3]) : 0;
|
||||
|
||||
Header = &PciHeader;
|
||||
|
||||
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);
|
||||
if (EFI_ERROR (Status)) {
|
||||
AsciiPrint ("No PCI devices found in the system\n");
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (Argc == 1) {
|
||||
// Dump all PCI devices
|
||||
AsciiPrint ("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
|
||||
AsciiPrint ("_____________________________________________________________");
|
||||
for (ThisBus = 0; ThisBus <= PCI_MAX_BUS; ThisBus++) {
|
||||
for (Index = 0; Index < HandleCount; Index++) {
|
||||
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);
|
||||
if (ThisBus != Bus) {
|
||||
continue;
|
||||
}
|
||||
AsciiPrint ("\n%03d.%02d.%02d", Bus, Dev, Func);
|
||||
Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), &PciHeader);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Hdr = &PciHeader.Bridge.Hdr;
|
||||
|
||||
if (Hdr->ClassCode[2] < sizeof (gPciDevClass)/sizeof (VOID *)) {
|
||||
Str = gPciDevClass[Hdr->ClassCode[2]];
|
||||
if (Hdr->ClassCode[2] == PCI_CLASS_SERIAL) {
|
||||
if (Hdr->ClassCode[1] < sizeof (gPciSerialClassCodes)/sizeof (VOID *)) {
|
||||
// print out Firewire or USB inplace of Serial Bus controllers
|
||||
Str = gPciSerialClassCodes[Hdr->ClassCode[1]];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Str = "Unknown device ";
|
||||
}
|
||||
AsciiPrint (" 0x%04x 0x%04x %a 0x%02x", Hdr->VendorId, Hdr->DeviceId, Str, Hdr->ClassCode[1]);
|
||||
}
|
||||
if (Seg != 0) {
|
||||
// Only print Segment if it is non zero. If you only have one PCI segment it is
|
||||
// redundent to print it out
|
||||
AsciiPrint (" Seg:%d", Seg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
AsciiPrint ("\n");
|
||||
} else {
|
||||
// Dump specific PCI device
|
||||
for (Index = 0; Index < HandleCount; Index++) {
|
||||
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);
|
||||
if ((Bus == BusArg) && (Dev == DevArg) && (Func == FuncArg)) {
|
||||
// Only print Segment if it is non zero. If you only have one PCI segment it is
|
||||
// redundent to print it out
|
||||
if (Seg != 0) {
|
||||
AsciiPrint ("Seg:%d ", Seg);
|
||||
}
|
||||
AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus, Dev, Func);
|
||||
|
||||
Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), Header);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Hdr = &PciHeader.Bridge.Hdr;
|
||||
if (IS_PCI_BRIDGE (&PciHeader.Bridge)) {
|
||||
Bridge = &PciHeader.Bridge.Bridge;
|
||||
AsciiPrint (
|
||||
"PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n",
|
||||
Bridge->PrimaryBus, Bridge->SecondaryBus, Bridge->SubordinateBus
|
||||
);
|
||||
AsciiPrint (" Bar 0: 0x%08x Bar 1: 0x%08x\n", Bridge->Bar[0], Bridge->Bar[1]);
|
||||
} else {
|
||||
Device = &PciHeader.Device.Device;
|
||||
AsciiPrint (
|
||||
"VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n",
|
||||
Hdr->VendorId, Hdr->DeviceId, Device->SubsystemVendorID, Device->SubsystemID
|
||||
);
|
||||
AsciiPrint (" Class Code: 0x%02x 0x%02x 0x%02x\n", Hdr->ClassCode[2], Hdr->ClassCode[1], Hdr->ClassCode[0]);
|
||||
for (Count = 0; Count < 6; Count++) {
|
||||
AsciiPrint (" Bar %d: 0x%08x\n", Count, Device->Bar[Count]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsciiPrint ("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FreePool (HandleBuffer);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdPciDebugTemplate[] = {
|
||||
"pci",
|
||||
" [bus] [dev] [func]; Dump PCI",
|
||||
NULL,
|
||||
EblPciCmd
|
||||
};
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwDebugTemplate[] =
|
||||
{
|
||||
{
|
||||
"md",
|
||||
" [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",
|
||||
NULL,
|
||||
EblMdCmd
|
||||
},
|
||||
{
|
||||
"mfill",
|
||||
" Addr Len [data] [1|2|4]; Memory Fill Addr Len*(1|2|4) bytes of data(0)",
|
||||
NULL,
|
||||
EblMfillCmd
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Initialize the commands in this in this file
|
||||
**/
|
||||
VOID
|
||||
EblInitializemdHwDebugCmds (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (FeaturePcdGet (PcdEmbeddedHwDebugCmd)) {
|
||||
EblAddCommands (mCmdHwDebugTemplate, sizeof (mCmdHwDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
if (FeaturePcdGet (PcdEmbeddedPciDebugCmd)) {
|
||||
EblAddCommands (mCmdPciDebugTemplate, sizeof (mCmdPciDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
}
|
||||
|
153
EmbeddedPkg/Ebl/HwIoDebug.c
Normal file
153
EmbeddedPkg/Ebl/HwIoDebug.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/** @file
|
||||
Hardware IO based debug commands
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
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.
|
||||
|
||||
Commands useful for debugging hardware. IO commands seperated out as not all
|
||||
processor architectures support the IO command.
|
||||
|
||||
**/
|
||||
|
||||
#include "Ebl.h"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Read from IO space
|
||||
|
||||
Argv[0] - "ioread"
|
||||
Argv[1] - Hex IO address
|
||||
Argv[2] - IO Width [1|2|4] with a default of 1
|
||||
|
||||
ior 0x3f8 4 ;Do a 32-bit IO Read from 0x3f8
|
||||
ior 0x3f8 1 ;Do a 8-bit IO Read from 0x3f8
|
||||
|
||||
@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
|
||||
EblIoReadCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
UINTN Width;
|
||||
UINTN Port;
|
||||
UINTN Data;
|
||||
|
||||
if (Argc < 2) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Port = AsciiStrHexToUintn (Argv[1]);
|
||||
Width = (Argc > 2) ? AsciiStrHexToUintn (Argv[2]) : 1;
|
||||
|
||||
if (Width == 1) {
|
||||
Data = IoRead8 (Port);
|
||||
} else if (Width == 2) {
|
||||
Data = IoRead16 (Port);
|
||||
} else if (Width == 4) {
|
||||
Data = IoRead32 (Port);
|
||||
} else {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
AsciiPrint ("0x%04x = 0x%x", Port, Data);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Write to IO space
|
||||
|
||||
Argv[0] - "iowrite"
|
||||
Argv[1] - Hex IO address
|
||||
Argv[2] - Hex data to write
|
||||
Argv[3] - IO Width [1|2|4] with a default of 1
|
||||
|
||||
iow 0x3f8 af 4 ;Do a 32-bit IO write of af to 0x3f8
|
||||
iow 0x3f8 af ;Do an 8-bit IO write of af to 0x3f8
|
||||
|
||||
@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
|
||||
EblIoWriteCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
UINTN Width;
|
||||
UINTN Port;
|
||||
UINTN Data;
|
||||
|
||||
if (Argc < 3) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Port = AsciiStrHexToUintn (Argv[1]);
|
||||
Data = AsciiStrHexToUintn (Argv[2]);
|
||||
Width = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 1;
|
||||
|
||||
if (Width == 1) {
|
||||
IoWrite8 (Port, (UINT8)Data);
|
||||
} else if (Width == 2) {
|
||||
IoWrite16 (Port, (UINT16)Data);
|
||||
} else if (Width == 4) {
|
||||
IoWrite32 (Port, (UINT32)Data);
|
||||
} else {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwIoDebugTemplate[] =
|
||||
{
|
||||
{
|
||||
"ioread",
|
||||
" Port [1|2|4]; IO read of width[1] byte(s) from Port",
|
||||
NULL,
|
||||
EblIoReadCmd
|
||||
},
|
||||
{
|
||||
"iowrite",
|
||||
" Port Data [1|2|4]; IO write Data of width[1] byte(s) to Port",
|
||||
NULL,
|
||||
EblIoWriteCmd
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Initialize the commands in this in this file
|
||||
**/
|
||||
VOID
|
||||
EblInitializemdHwIoDebugCmds (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (FeaturePcdGet (PcdEmbeddedIoEnable)) {
|
||||
EblAddCommands (mCmdHwIoDebugTemplate, sizeof (mCmdHwIoDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
}
|
||||
|
616
EmbeddedPkg/Ebl/Main.c
Normal file
616
EmbeddedPkg/Ebl/Main.c
Normal file
@@ -0,0 +1,616 @@
|
||||
/** @file
|
||||
Basic command line parser for EBL (Embedded Boot Loader)
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
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"
|
||||
|
||||
// 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 seperators 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_SEPERATOR allows mult commands on a single line
|
||||
InQuote = FALSE;
|
||||
LookingForArg = TRUE;
|
||||
for (Char = CmdLine, Arg = 0; *Char != '\0'; Char++) {
|
||||
if (!InQuote && *Char == CMD_SEPERATOR) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Perform any text coversion here
|
||||
if (*Char == '\t') {
|
||||
// TAB to space
|
||||
*Char = ' ';
|
||||
}
|
||||
|
||||
if (LookingForArg) {
|
||||
// Look for the beging 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 == '"')) || (!InQuote && (*Char == ' '))) {
|
||||
*Char = '\0';
|
||||
LookingForArg = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*Argc = Arg;
|
||||
|
||||
if (*Char == CMD_SEPERATOR) {
|
||||
// Replace the command delimeter 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 funciton is called evey 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. Carage 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
|
||||
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 dev@edk2.tianocore.org\n");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Print the prompt for the EBL.
|
||||
**/
|
||||
VOID
|
||||
EblPrompt (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EblSetTextColor (EFI_YELLOW);
|
||||
AsciiPrint ((CHAR8 *)PcdGetPtr (PcdEmbeddedPrompt));
|
||||
EblSetTextColor (0);
|
||||
AsciiPrint ("%a", ">");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Parse a command line and execute the commands. The ; seperator 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 seperated 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 imput 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
for each command line.
|
||||
|
||||
@param ImageHandle EFI ImageHandle for this application.
|
||||
@param SystemTable EFI system table
|
||||
|
||||
@return EFI status of the applicaiton
|
||||
|
||||
**/
|
||||
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 commnads
|
||||
EblInitializeCmdTable ();
|
||||
EblInitializeDeviceCmd ();
|
||||
EblInitializemdHwDebugCmds ();
|
||||
EblInitializemdHwIoDebugCmds ();
|
||||
EblInitializeDirCmd ();
|
||||
EblInitializeHobCmd ();
|
||||
EblInitializeScriptCmd ();
|
||||
EblInitializeExternalCmd ();
|
||||
EblInitializeNetworkCmd();
|
||||
|
||||
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);
|
||||
|
||||
// Disable the 5 minute EFI watchdog time so we don't get automatically reset
|
||||
gBS->SetWatchdogTimer (0, 0, 0, NULL);
|
||||
}
|
||||
|
||||
// Save current screen mode
|
||||
gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &gScreenColumns, &gScreenRows);
|
||||
|
||||
EblPrintStartupBanner ();
|
||||
|
||||
// Parse command line and handle commands seperated 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
104
EmbeddedPkg/Ebl/Network.c
Normal file
104
EmbeddedPkg/Ebl/Network.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/** @file
|
||||
EBL commands for Network Devices
|
||||
|
||||
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"
|
||||
|
||||
EFI_STATUS
|
||||
ParseIp (
|
||||
IN CHAR8 *String,
|
||||
OUT EFI_IP_ADDRESS *Address
|
||||
)
|
||||
{
|
||||
Address->v4.Addr[0] = AsciiStrDecimalToUintn(String);
|
||||
String = AsciiStrStr(String, ".") + 1;
|
||||
Address->v4.Addr[1] = AsciiStrDecimalToUintn(String);
|
||||
String = AsciiStrStr(String, ".") + 1;
|
||||
Address->v4.Addr[2] = AsciiStrDecimalToUintn(String);
|
||||
String = AsciiStrStr(String, ".") + 1;
|
||||
Address->v4.Addr[3] = AsciiStrDecimalToUintn(String);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EblIpCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status = EFI_INVALID_PARAMETER;
|
||||
EFI_MAC_ADDRESS Mac;
|
||||
EFI_IP_ADDRESS Ip;
|
||||
|
||||
if (Argc == 1) {
|
||||
// Get current IP/MAC
|
||||
|
||||
// Get current MAC address
|
||||
Status = EblGetCurrentMacAddress (&Mac);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
AsciiPrint ("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", Mac.Addr[0], Mac.Addr[1], Mac.Addr[2], Mac.Addr[3], Mac.Addr[4], Mac.Addr[5]);
|
||||
|
||||
// Get current IP address
|
||||
Status = EblGetCurrentIpAddress (&Ip);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("IP Address is not configured.\n");
|
||||
Status = EFI_SUCCESS;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
AsciiPrint("IP Address: %d.%d.%d.%d\n", Ip.v4.Addr[0], Ip.v4.Addr[1],Ip.v4.Addr[2], Ip.v4.Addr[3]);
|
||||
|
||||
} else if ((Argv[1][0] == 'r') && (Argc == 2)) {
|
||||
// Get new address via dhcp
|
||||
Status = EblPerformDHCP (TRUE);
|
||||
} else if ((Argv[1][0] == 's') && (Argc == 3)) {
|
||||
// Set static IP
|
||||
Status = ParseIp (Argv[2], &Ip);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EblSetStationIp (&Ip, NULL);
|
||||
}
|
||||
|
||||
Exit:
|
||||
return Status;
|
||||
}
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdNetworkTemplate[] =
|
||||
{
|
||||
{
|
||||
"ip",
|
||||
" ; print current ip address\n\r [r]; request DHCP address\n\r [s] ipaddr; set static IP address",
|
||||
NULL,
|
||||
EblIpCmd
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Initialize the commands in this in this file
|
||||
**/
|
||||
VOID
|
||||
EblInitializeNetworkCmd (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EblAddCommands (mCmdNetworkTemplate, sizeof (mCmdNetworkTemplate)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
|
126
EmbeddedPkg/Ebl/Script.c
Normal file
126
EmbeddedPkg/Ebl/Script.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/** @file
|
||||
Script command allows the execution of commands from a text file
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
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.
|
||||
|
||||
Module Name: EfiDevice.c
|
||||
|
||||
**/
|
||||
|
||||
#include "Ebl.h"
|
||||
|
||||
|
||||
/**
|
||||
Execute the passed in file like a series of commands. The ; can be used on
|
||||
a single line to indicate multiple commands per line. The Ascii text file
|
||||
can contain any number of lines. The following line termination forms are
|
||||
supported:
|
||||
LF : Unix, Mac OS X*, BeOS
|
||||
CR+LF: MS-DOS*, Microsoft Windows*
|
||||
CR : Commodore, Apple II, and realy Mac OS
|
||||
LF+CR: for simplicity and completeness
|
||||
|
||||
Argv[0] - "script"
|
||||
Argv[1] - Device Name:path for the file to load
|
||||
|
||||
script fv1:\script.txt
|
||||
|
||||
@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
|
||||
EblScriptCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_OPEN_FILE *File;
|
||||
VOID *Address;
|
||||
UINTN Size;
|
||||
CHAR8 *Ptr;
|
||||
CHAR8 *ScanPtr;
|
||||
UINTN CmdLineSize;
|
||||
|
||||
|
||||
|
||||
if (Argc < 2) {
|
||||
// file name required
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File == NULL) {
|
||||
AsciiPrint (" %a is not a valid path\n", Argv[1]);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Status = EfiReadAllocatePool (File, &Address, &Size);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
// Loop through each line in the text file
|
||||
for (Ptr = (CHAR8 *)Address; (Ptr < (((CHAR8 *)Address) + Size)) && !EFI_ERROR (Status); Ptr += CmdLineSize) {
|
||||
for (CmdLineSize = 0, ScanPtr = Ptr; ; CmdLineSize++, ScanPtr++) {
|
||||
// look for the end of the line
|
||||
if ((*ScanPtr == EBL_CR) || (*ScanPtr == EBL_LF)) {
|
||||
// convert to NULL as this is what input routine would do
|
||||
*ScanPtr = 0;
|
||||
if ((*(ScanPtr + 1) == EBL_CR) || (*(ScanPtr + 1) == EBL_LF)) {
|
||||
// if its a set get the 2nd EOL char
|
||||
CmdLineSize++;
|
||||
*(ScanPtr + 1) = 0;
|
||||
}
|
||||
CmdLineSize++;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Status = ProcessCmdLine (Ptr, CmdLineSize);
|
||||
}
|
||||
|
||||
FreePool (Address);
|
||||
}
|
||||
|
||||
EfiClose (File);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mScriptTemplate[] = {
|
||||
{
|
||||
"script",
|
||||
" device:path; load an ascii file and execute it like commands",
|
||||
NULL,
|
||||
EblScriptCmd
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Initialize the commands in this in this file
|
||||
**/
|
||||
|
||||
VOID
|
||||
EblInitializeScriptCmd (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (FeaturePcdGet (PcdEmbeddedScriptCmd)) {
|
||||
EblAddCommands (mScriptTemplate, sizeof (mScriptTemplate)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user