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:
AJFISH
2009-12-06 01:57:05 +00:00
parent f7753a96ba
commit 2ef2b01e07
294 changed files with 47954 additions and 0 deletions

View File

@@ -0,0 +1,119 @@
/** @file
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 <Uefi.h>
#include <Library/CacheMaintenanceLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/Cpu.h>
#include <Protocol/DebugSupport.h>
#include <Protocol/TimerDebugSupport.h>
EFI_STATUS
EFIAPI
DebugSupportGetMaximumProcessorIndex (
IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
OUT UINTN *MaxProcessorIndex
)
{
if (MaxProcessorIndex == NULL) {
return EFI_INVALID_PARAMETER;
}
*MaxProcessorIndex = 0;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
DebugSupportRegisterPeriodicCallback (
IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
IN UINTN ProcessorIndex,
IN EFI_PERIODIC_CALLBACK PeriodicCallback
)
{
TIMER_DEBUG_SUPPORT_PROTOCOL *Timer;
EFI_STATUS Status;
Status = gBS->LocateProtocol(&gTimerDebugSupportProtocolGuid, NULL, (VOID **)&Timer);
if (EFI_ERROR(Status)) {
return Status;
}
Status = Timer->RegisterPeriodicCallback(Timer, PeriodicCallback);
return Status;
}
EFI_STATUS
EFIAPI
DebugSupportRegisterExceptionCallback (
IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
IN UINTN ProcessorIndex,
IN EFI_EXCEPTION_CALLBACK ExceptionCallback,
IN EFI_EXCEPTION_TYPE ExceptionType
)
{
EFI_CPU_ARCH_PROTOCOL *Cpu;
EFI_STATUS Status;
Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
if (EFI_ERROR(Status)) {
return Status;
}
Status = Cpu->RegisterInterruptHandler(Cpu, ExceptionType, (EFI_CPU_INTERRUPT_HANDLER)ExceptionCallback);
return Status;
}
EFI_STATUS
EFIAPI
DebugSupportInvalidateInstructionCache (
IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
IN UINTN ProcessorIndex,
IN VOID *Start,
IN UINT64 Length
)
{
InvalidateInstructionCacheRange(Start, Length);
return EFI_SUCCESS;
}
EFI_DEBUG_SUPPORT_PROTOCOL mDebugSupport = {
IsaArm,
DebugSupportGetMaximumProcessorIndex,
DebugSupportRegisterPeriodicCallback,
DebugSupportRegisterExceptionCallback,
DebugSupportInvalidateInstructionCache
};
EFI_STATUS
DebugSupportDxeInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE Handle = NULL;
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiDebugSupportProtocolGuid);
Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiDebugSupportProtocolGuid, &mDebugSupport, NULL);
return Status;
}

View File

@@ -0,0 +1,28 @@
#%HEADER%
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = ArmDebugSupportDxe
FILE_GUID = 2e7c151b-cbd8-4df6-a0e3-cde660067c6a
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = DebugSupportDxeInitialize
[Sources.common]
DebugSupport.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedePkg/EmbeddedePkg.dec
[LibraryClasses]
BaseMemoryLib
CacheMaintenanceLib
UefiDriverEntryPoint
ArmLib
[Protocols]
gEfiCpuArchProtocolGuid
gEfiDebugSupportProtocolGuid
gTimerDebugSupportProtocolGuid

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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));
}
}

View File

@@ -0,0 +1,152 @@
/** @file
Glue code that contains the EFI entry point and converts it to an EBL
ASCII Argc, Argv sytle entry point
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.
**/
#define CMD_SEPERATOR ';'
#define MAX_ARGS 32
EFI_STATUS
EblMain (
IN UINTN Argc,
IN CHAR8 **Argv
);
///
/// EdkExternCmdEntry() & ParseArguments() convert the standard EFI entry point
/// into Argc, Argv form that calls EblMain().
///
/**
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 CmdLineSize Size of CmdLine in bytes
@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
**/
VOID
ParseArguments (
IN CHAR8 *CmdLine,
IN UINTN CmdLineSize,
OUT UINTN *Argc,
OUT CHAR8 **Argv
)
{
UINTN Arg;
CHAR8 *Char;
BOOLEAN LookingForArg;
BOOLEAN InQuote;
UINTN Index;
*Argc = 0;
if ((CmdLineSize == 0) || (AsciiStrLen (CmdLine) == 0)) {
// basic error checking failed on the arguments
return;
}
// Walk a single command line. A CMD_SEPERATOR allows mult commands on a single line
InQuote = FALSE;
LookingForArg = TRUE;
for (Char = CmdLine, Arg = 0, Index = 0; *Char != '\0' && *Char != CMD_SEPERATOR; Char++, Index++) {
// 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;
}
}
if ((Arg >= MAX_ARGS) || (Index > CmdLineSize)) {
// Error check buffer and exit since it does not look valid
break;
}
}
*Argc = Arg;
if (*Char == CMD_SEPERATOR) {
// Replace the command delimeter with null
*Char = '\0';
}
return;
}
/**
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
EdkExternCmdEntry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
UINTN Argc;
CHAR8 *Argv[MAX_ARGS];
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);
if (EFI_ERROR (Status)) {
Argc = 0;
} else {
// Looks like valid commands were passed in.
ParseArguments (ImageInfo->LoadOptions, ImageInfo->LoadOptionsSize, &Argc, Argv);
}
return EblMain (Argc, Argv);
}

View File

@@ -0,0 +1,52 @@
/** @file
Example of an external EBL command. It's loaded via EBL start command.
Argc and Argv are passed in via "" of the EBL command line.
Start fs0:\EdkExternCmd.efi "Argv[0] Argv[1] 2"
will launch this command with
Argv[0] = "Argv[0]"
Argv[1] = "Argv[2]"
Argv[2] = "3"
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.
**/
/**
Entry point with Argc, Argv. Put your code here.
@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
EblMain (
IN UINTN Argc,
IN CHAR8 **Argv
)
{
UINTN Index;
AsciiPrint ("Hello World\n");
for (Index = 0; Index < Argc; Index++) {
AsciiPrint ("Argv[%d] = %a\n", Index, Argv[Index]);
}
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,82 @@
/** @file
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 <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Protocol/MonotonicCounter.h>
UINT64 gCurrentMonotonicCount = 0;
EFI_STATUS
EFIAPI
GetNextMonotonicCount (
OUT UINT64 *Count
)
{
if (Count == NULL) {
return EFI_INVALID_PARAMETER;
}
*Count = gCurrentMonotonicCount++;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
GetNextHighMonotonicCount (
OUT UINT32 *HighCount
)
{
if (HighCount == NULL) {
return EFI_INVALID_PARAMETER;
}
gCurrentMonotonicCount += 0x0000000100000000ULL;
*HighCount = RShiftU64 (gCurrentMonotonicCount, 32) & 0xFFFFFFFF;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
MonotonicCounterDriverInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE Handle = NULL;
// Make sure the Monotonic Counter Architectural Protocol is not already installed in the system
ASSERT_PROTOCOL_ALREADY_INSTALLED(NULL, &gEfiMonotonicCounterArchProtocolGuid);
// Fill in the EFI Boot Services and EFI Runtime Services Monotonic Counter Fields
gBS->GetNextMonotonicCount = GetNextMonotonicCount;
gRT->GetNextHighMonotonicCount = GetNextHighMonotonicCount;
// Install the Monotonic Counter Architctural Protocol onto a new handle
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEfiMonotonicCounterArchProtocolGuid, NULL,
NULL
);
return Status;
}

View File

@@ -0,0 +1,29 @@
#%HEADER%
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = EmbeddedMonotonicCounter
FILE_GUID = FCABE6A7-7953-4A84-B7EC-D29E89B62E87
MODULE_TYPE = DXE_RUNTIME_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = MonotonicCounterDriverInitialize
[Sources.common]
EmbeddedMonotonicCounter.c
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
BaseLib
DebugLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiRuntimeServicesTableLib
[Protocols]
gEfiMonotonicCounterArchProtocolGuid
[Depex]
TRUE

126
EmbeddedPkg/EmbeddedPkg.dec Normal file
View File

@@ -0,0 +1,126 @@
#%HEADER%
#/** @file
# Framework Module Development Environment Industry Standards
#
# This Package provides headers and libraries that conform to EFI/PI Industry standards.
# 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]
DEC_SPECIFICATION = 0x00010005
PACKAGE_NAME = EmbeddedPkg
PACKAGE_GUID = dea8e498-7e1b-47c1-b6fa-4bc04092587e
PACKAGE_VERSION = 0.1
################################################################################
#
# Include Section - list of Include Paths that are provided by this package.
# Comments are used for Keywords and Module Types.
#
# Supported Module Types:
# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
#
################################################################################
[Includes.common]
Include # Root include for the package
[LibraryClasses.common]
EfiFileLib|Include/Library/EfiFileLib.h
PrePiLib|Include/Library/PrePiLib.h
RealTimeClockLib|Include/Library/RealTimeClockLib.h
EfiResetSystemLib|Include/Library/EfiResetSystemLib.h
EblCmdLib|Include/Library/EblCmdLib.h
EblAddExternalCommandLib|Library/EblAddExternalCommandLib.h
EblNetworkLib|Library/EblNetworkLib.h
GdbSerialLib|Include/Library/GdbSerialLib.h
[Guids.common]
gEmbeddedTokenSpaceGuid = { 0xe0d8ca17, 0x4276, 0x4386, { 0xbb, 0x79, 0x48, 0xcb, 0x81, 0x3d, 0x3c, 0x4f }}
[Protocols.common]
gHardwareInterruptProtocolGuid = { 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } }
gEfiDebugSupportPeriodicCallbackProtocolGuid = { 0x9546e07c, 0x2cbb, 0x4c88, { 0x98, 0x6c, 0xcd, 0x34, 0x10, 0x86, 0xf0, 0x44 } }
gEfiEblAddCommandProtocolGuid = { 0xaeda2428, 0x9a22, 0x4637, { 0x9b, 0x21, 0x54, 0x5e, 0x28, 0xfb, 0xb8, 0x29 } }
gEmbeddedDeviceGuid = { 0xbf4b9d10, 0x13ec, 0x43dd, { 0x88, 0x80, 0xe9, 0xb, 0x71, 0x8f, 0x27, 0xde } }
gEmbeddedExternalDeviceProtocolGuid = { 0x735F8C64, 0xD696, 0x44D0, { 0xBD, 0xF2, 0x44, 0x7F, 0xD0, 0x5A, 0x54, 0x06 }}
gEmbeddedGpioProtocolGuid = { 0x17a0a3d7, 0xc0a5, 0x4635, { 0xbb, 0xd5, 0x07, 0x21, 0x87, 0xdf, 0xe2, 0xee }}
[PcdsFeatureFlag.common]
gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|FALSE|BOOLEAN|0x00000001
gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE|BOOLEAN|0x00000002
gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE|BOOLEAN|0x00000003
gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE|BOOLEAN|0x00000004
gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE|BOOLEAN|0x00000005
gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE|BOOLEAN|0x00000006
gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|FALSE|BOOLEAN|0x00000041
gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|FALSE|BOOLEAN|0x0000001b
gEmbeddedTokenSpaceGuid.PcdCacheEnable|FALSE|BOOLEAN|0x00000042
gEmbeddedTokenSpaceGuid.PcdGdbSerial|FALSE|BOOLEAN|0x0000004d
[PcdsFixedAtBuild.common]
gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|L""|VOID*|0x00000007
gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07|UINT32|0x00000008
gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000|UINT32|0x00000009
gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"Ebl"|VOID*|0x00000034
gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|131072|UINT32|0x00000040
gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0|UINT32|0x0000000b
gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|131072|UINT32|0x0000000c
gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0|UINT32|0x000000d
gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0|UINT32|0x000000e
gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0|UINT32|0x0000000f
gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32|UINT8|0x00000010
gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0|UINT8|0x00000011
gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|0x0|UINT32|0x00000043
gEmbeddedTokenSpaceGuid.PcdFlashFvMainOffset|0x0|UINT32|0x00000044
gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize|0x0|UINT32|0x000000045
# Used to help reduce fragmentation in the EFI memory map
# EFI Pages (4K) are the units used
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0|UINT32|0x00000012
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0|UINT32|0x00000013
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0|UINT32|0x00000014
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0|UINT32|0x00000015
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0|UINT32|0x00000016
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|0|UINT32|0x00000017
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|0|UINT32|0x00000018
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|0|UINT32|0x00000019
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0|UINT32|0x0000001a
gEmbeddedTokenSpaceGuid.PcdTimerBaseAddress|0x3c700000|UINT32|0x0000001c
gEmbeddedTokenSpaceGuid.PcdTimerVector|7|UINT32|0x0000001d
gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000|UINT32|0x0000001e
gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress|0x38e00000|UINT32|0x0000001f
gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress|0xffff0000|UINT32|0x00000030
gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize|0x0000000|UINT32|0x00000031
gEmbeddedTokenSpaceGuid.PcdEmbeddedPerformanceCounterFreqencyInHz|0x0000000|UINT64|0x00000032
gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds|0x0000000|UINT32|0x00000033
# Shell characteristics
gEmbeddedTokenSpaceGuid.PcdEmbeddedShellCharacterEcho|TRUE|BOOLEAN|0x00000046
gEmbeddedTokenSpaceGuid.PcdGdbBaudRate|115200|UINT64|0x00000047
gEmbeddedTokenSpaceGuid.PcdGdbDataBits|8|UINT8|0x00000048
gEmbeddedTokenSpaceGuid.PcdGdbParity|1|UINT8|0x00000049
gEmbeddedTokenSpaceGuid.PcdGdbStopBits|1|UINT8|0x0000004a
gEmbeddedTokenSpaceGuid.PcdGdbUartPort|0x3f8|UINT32|0x0000004b
gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount|10000000|UINT32|0x0000004c

266
EmbeddedPkg/EmbeddedPkg.dsc Normal file
View File

@@ -0,0 +1,266 @@
#%HEADER%
#/** @file
# Embedded Package
#
#
# 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]
PLATFORM_NAME = Embedded
PLATFORM_GUID = 8DBB580B-CF89-4D57-95C6-DFE96C44686E
PLATFORM_VERSION = 0.1
DSC_SPECIFICATION = 0x00010005
OUTPUT_DIRECTORY = Build/Embedded
SUPPORTED_ARCHITECTURES = IA32|X64|IPF|ARM
BUILD_TARGETS = DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT
FLASH_DEFINITION = EmbeddedPkg/EmbeddedPkg.fdf
################################################################################
#
# SKU Identification section - list of all SKU IDs supported by this
# Platform.
#
################################################################################
[SkuIds]
0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.
################################################################################
#
# Library Class section - list of all Library Classes needed by this Platform.
#
################################################################################
[LibraryClasses.common]
# DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
EfiFileLib|EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
SerialPortLib|EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf
RealTimeClockLib|EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf
EfiResetSystemLib|EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf
GdbSerialLib|EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf
#
# Need to change this for IPF
#
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
EblCmdLib|EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf
EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf
[LibraryClasses.common.DXE_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
[LibraryClasses.common.UEFI_APPLICATION]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
[LibraryClasses.common.UEFI_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf
[LibraryClasses.common.SEC]
ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf
[LibraryClasses.ARM]
SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf
################################################################################
#
# Pcd Section - list of all PCD Entries defined by this Platform
#
################################################################################
[PcdsFeatureFlag.common]
gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE
gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|FALSE
gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|FALSE
gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|FALSE
#
# Control what commands are supported from the UI
# Turn these on and off to add features or save size
#
gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|TRUE
gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE
gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE
gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE
gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE
gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE
gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|TRUE
gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|FALSE
[PcdsFixedAtBuild.common]
gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000
gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000
gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000
gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF
gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0
gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000
gEfiMdePkgTokenSpaceGuid.PcdFSBClock|200000000
gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000
gEfiMdePkgTokenSpaceGuid.PcdFSBClock|200000000
gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|L""|VOID*|2
gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07
gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000
gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|0
gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0
gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|0
gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0
gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0
gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0
#
# Optinal feature to help prevent EFI memory map fragments
# Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob
# Values are in EFI Pages (4K). DXE Core will make sure that
# at least this much of each type of memory can be allocated
# from a single memory range. This way you only end up with
# maximum of two fragements for each type in the memory map
# (the memory used, and the free memory that was prereserved
# but not used).
#
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|0
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|0
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|0
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0
#
# Timer config for this platform
#
gEmbeddedTokenSpaceGuid.PcdTimerBaseAddress|0x3c700000
gEmbeddedTokenSpaceGuid.PcdTimerVector|7
gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000
[PcdsFixedAtBuild.ARM]
gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32
gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0
[PcdsFixedAtBuild.IA32]
gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|36
gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16
[PcdsFixedAtBuild.X64]
gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|52
gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16
[PcdsFixedAtBuild.IPF]
gEfiMdePkgTokenSpaceGuid.PcdIoBlockBaseAddressForIpf|0x0ffffc000000
#
# This makes it so you can source level debug with NT32. VC++ debugger limitiation!
#
#[BuildOptions]
# DEBUG_*_IA32_DLINK_FLAGS = /EXPORT:InitializeDriver=$(IMAGE_ENTRY_POINT) /ALIGN:4096 /SUBSYSTEM:CONSOLE
# RELEASE_*_IA32_DLINK_FLAGS = /ALIGN:4096
# *_*_IA32_CC_FLAGS = /D EFI_SPECIFICATION_VERSION=0x0002000A /D TIANO_RELEASE_VERSION=0x00080006
################################################################################
#
# Components Section - list of all Modules needed by this Platform
#
################################################################################
[Components.common]
EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf
EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf
EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf
EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf # ApplePkg
EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf # ApplePkg
EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf
EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf
EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf
EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf
####ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf ???
EmbeddedPkg/Ebl/Ebl.inf
#### EmbeddedPkg/EblExternCmd/EblExternCmd.inf
EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf
EmbeddedPkg/GdbStub/GdbStub.inf
EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
EmbeddedPkg/SerialDxe/SerialDxe.inf
EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf
EmbeddedPkg/TemplateBds/TemplateBds.inf
EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf
EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf
EmbeddedPkg/TemplateSec/TemplateSec.inf
EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf

141
EmbeddedPkg/EmbeddedPkg.fdf Normal file
View File

@@ -0,0 +1,141 @@
# This is Ebl FDF file
#
# Copyright (c) 2008, 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.
#
################################################################################
#
# FV Section
#
# [FV] section is used to define what components or modules are placed within a flash
# device file. This section also defines order the components and modules are positioned
# within the image. The [FV] section consists of define statements, set statements and
# module statements.
#
################################################################################
[FV.FvLoad]
FvAlignment = 16 #FV alignment and FV attributes setting.
ERASE_POLARITY = 1
MEMORY_MAPPED = TRUE
STICKY_WRITE = TRUE
LOCK_CAP = TRUE
LOCK_STATUS = TRUE
WRITE_DISABLED_CAP = TRUE
WRITE_ENABLED_CAP = TRUE
WRITE_STATUS = TRUE
WRITE_LOCK_CAP = TRUE
WRITE_LOCK_STATUS = TRUE
READ_DISABLED_CAP = TRUE
READ_ENABLED_CAP = TRUE
READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
################################################################################
#
# The INF statements point to module INF files, which will be placed into this FV image.
# Parsing tools will scan the INF file to determine the type of component or module.
# The component or module type is used to reference the standard rules
# defined elsewhere in the FDF file.
#
# The format for INF statements is:
# INF $(PathAndInfFileName)
#
################################################################################
INF EmbeddedPkg/Ebl/Ebl.inf
################################################################################
#
# Rules are use with the [FV] section's module INF type to define
# how an FFS file is created for a given INF file. The following Rule are the default
# rules for the different module type. User can add the customized rules to define the
# content of the FFS file.
#
################################################################################
############################################################################
# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section #
############################################################################
#
#[Rule.Common.DXE_DRIVER]
# FILE DRIVER = $(NAMED_GUID) {
# DXE_DEPEX DXE_DEPEX Optional |.depex
# COMPRESS PI_STD {
# GUIDED {
# PE32 PE32 |.efi
# UI STRING="$(MODULE_NAME)" Optional
# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
# }
# }
# }
#
############################################################################
[Rule.Common.SEC]
FILE SEC = $(NAMED_GUID) {
PE32 PE32 |.efi
}
[Rule.Common.PEI_CORE]
FILE PEI_CORE = $(NAMED_GUID) {
PE32 PE32 |.efi
UI STRING ="$(MODULE_NAME)" Optional
}
[Rule.Common.PEIM]
FILE PEIM = $(NAMED_GUID) {
PEI_DEPEX PEI_DEPEX Optional |.depex
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
}
[Rule.Common.PEIM.TIANOCOMPRESSED]
FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
PEI_DEPEX PEI_DEPEX Optional |.depex
GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
}
}
[Rule.Common.DXE_CORE]
FILE DXE_CORE = $(NAMED_GUID) {
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
}
[Rule.Common.UEFI_DRIVER]
FILE DRIVER = $(NAMED_GUID) {
DXE_DEPEX DXE_DEPEX Optional |.depex
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
}
[Rule.Common.DXE_DRIVER]
FILE DRIVER = $(NAMED_GUID) {
DXE_DEPEX DXE_DEPEX Optional |.depex
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
}
[Rule.Common.DXE_RUNTIME_DRIVER]
FILE DRIVER = $(NAMED_GUID) {
DXE_DEPEX DXE_DEPEX Optional |.depex
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
}
[Rule.Common.UEFI_APPLICATION]
FILE APPLICATION = $(NAMED_GUID) {
PE32 PE32 |.efi
UI STRING="$(MODULE_NAME)" Optional
}

View File

@@ -0,0 +1,717 @@
/** @file
Processor specific parts of the GDB stub
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.
**/
/** @file
Copyright (c) 2008, Apple, Inc
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 <GdbStubInternal.h>
#include <Library/CacheMaintenanceLib.h>
#include <Library/PrintLib.h>
//
// Array of exception types that need to be hooked by the debugger
// (efi, gdb) //efi number
//
EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
{ EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP }
// { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP },
// { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP },
// { EXCEPT_ARM_DATA_ABORT, GDB_SIGEMT },
// { EXCEPT_ARM_RESERVED, GDB_SIGILL }
};
// Shut up some annoying RVCT warnings
#ifdef __CC_ARM
#pragma diag_suppress 1296
#endif
UINTN gRegisterOffsets[] = {
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R0),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R1),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R2),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R3),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R4),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R5),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R6),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R7),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R8),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R9),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R10),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R11),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R12),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, SP),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, LR),
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, PC),
0x00000F01, // f0
0x00000F02,
0x00000F03,
0x00000F11, // f1
0x00000F12,
0x00000F13,
0x00000F21, // f2
0x00000F22,
0x00000F23,
0x00000F31, // f3
0x00000F32,
0x00000F33,
0x00000F41, // f4
0x00000F42,
0x00000F43,
0x00000F51, // f5
0x00000F52,
0x00000F53,
0x00000F61, // f6
0x00000F62,
0x00000F63,
0x00000F71, // f7
0x00000F72,
0x00000F73,
0x00000FFF, // fps
0x00000FFF,
0x00000FFF,
OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, CPSR)
};
// restore warnings for RVCT
#ifdef __CC_ARM
#pragma diag_default 1296
#endif
/**
Return the number of entries in the gExceptionType[]
@retval UINTN, the number of entries in the gExceptionType[] array.
**/
UINTN
MaxEfiException (
VOID
)
{
return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
}
/**
Return the number of entries in the gRegisters[]
@retval UINTN, the number of entries (registers) in the gRegisters[] array.
**/
UINTN
MaxRegisterCount (
VOID
)
{
return sizeof (gRegisterOffsets)/sizeof (UINTN);
}
/**
Check to see if the ISA is supported.
ISA = Instruction Set Architecture
@retval TRUE if Isa is supported
**/
BOOLEAN
CheckIsa (
IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
)
{
if (Isa == IsaArm) {
return TRUE;
} else {
return FALSE;
}
}
/**
This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
It is, by default, set to find the register pointer of the ARM member
@param SystemContext Register content at time of the exception
@param RegNumber The register to which we want to find a pointer
@retval the pointer to the RegNumber-th pointer
**/
UINTN *
FindPointerToRegister(
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber
)
{
UINT8 *TempPtr;
ASSERT(gRegisterOffsets[RegNumber] < 0xF00);
TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber];
return (UINT32 *)TempPtr;
}
/**
Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
@param SystemContext Register content at time of the exception
@param RegNumber the number of the register that we want to read
@param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
@retval the pointer to the next character of the output buffer that is available to be written on.
**/
CHAR8 *
BasicReadRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber,
IN CHAR8 *OutBufPtr
)
{
UINTN RegSize;
CHAR8 Char;
if (gRegisterOffsets[RegNumber] > 0xF00) {
AsciiSPrint(OutBufPtr, 9, "00000000");
OutBufPtr += 8;
return OutBufPtr;
}
RegSize = 0;
while (RegSize < 32) {
Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
if ((Char >= 'A') && (Char <= 'F')) {
Char = Char - 'A' + 'a';
}
*OutBufPtr++ = Char;
Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];
if ((Char >= 'A') && (Char <= 'F')) {
Char = Char - 'A' + 'a';
}
*OutBufPtr++ = Char;
RegSize = RegSize + 8;
}
return OutBufPtr;
}
/** p n
Reads the n-th register's value into an output buffer and sends it as a packet
@param SystemContext Register content at time of the exception
@param InBuffer Pointer to the input buffer received from gdb server
**/
VOID
ReadNthRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
)
{
UINTN RegNumber;
CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
CHAR8 *OutBufPtr; // pointer to the output buffer
RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
if (RegNumber >= MaxRegisterCount()) {
SendError (GDB_EINVALIDREGNUM);
return;
}
OutBufPtr = OutBuffer;
OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);
*OutBufPtr = '\0'; // the end of the buffer
SendPacket(OutBuffer);
}
/** g
Reads the general registers into an output buffer and sends it as a packet
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
ReadGeneralRegisters (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
UINTN Index;
CHAR8 *OutBuffer;
CHAR8 *OutBufPtr;
UINTN RegisterCount = MaxRegisterCount();
// It is not safe to allocate pool here....
OutBuffer = AllocatePool((RegisterCount * 8) + 1); // 8 bytes per register in string format plus a null to terminate
OutBufPtr = OutBuffer;
for (Index = 0; Index < RegisterCount; Index++) {
OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr);
}
*OutBufPtr = '\0';
SendPacket(OutBuffer);
FreePool(OutBuffer);
}
/**
Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
@param SystemContext Register content at time of the exception
@param RegNumber the number of the register that we want to write
@param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
@retval the pointer to the next character of the input buffer that can be used
**/
CHAR8
*BasicWriteRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber,
IN CHAR8 *InBufPtr
)
{
UINTN RegSize;
UINTN TempValue; // the value transferred from a hex char
UINT32 NewValue; // the new value of the RegNumber-th Register
if (gRegisterOffsets[RegNumber] > 0xF00) {
return InBufPtr + 8;
}
NewValue = 0;
RegSize = 0;
while (RegSize < 32) {
TempValue = HexCharToInt(*InBufPtr++);
if ((INTN)TempValue < 0) {
SendError (GDB_EBADMEMDATA);
return NULL;
}
NewValue += (TempValue << (RegSize+4));
TempValue = HexCharToInt(*InBufPtr++);
if ((INTN)TempValue < 0) {
SendError (GDB_EBADMEMDATA);
return NULL;
}
NewValue += (TempValue << RegSize);
RegSize = RegSize + 8;
}
*(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;
return InBufPtr;
}
/** P n...=r...
Writes the new value of n-th register received into the input buffer to the n-th register
@param SystemContext Register content at time of the exception
@param InBuffer Ponter to the input buffer received from gdb server
**/
VOID
WriteNthRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
)
{
UINTN RegNumber;
CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
CHAR8 *RegNumBufPtr;
CHAR8 *InBufPtr; // pointer to the input buffer
// find the register number to write
InBufPtr = &InBuffer[1];
RegNumBufPtr = RegNumBuffer;
while (*InBufPtr != '=') {
*RegNumBufPtr++ = *InBufPtr++;
}
*RegNumBufPtr = '\0';
RegNumber = AsciiStrHexToUintn (RegNumBuffer);
// check if this is a valid Register Number
if (RegNumber >= MaxRegisterCount()) {
SendError (GDB_EINVALIDREGNUM);
return;
}
InBufPtr++; // skips the '=' character
BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
SendSuccess();
}
/** G XX...
Writes the new values received into the input buffer to the general registers
@param SystemContext Register content at time of the exception
@param InBuffer Pointer to the input buffer received from gdb server
**/
VOID
EFIAPI
WriteGeneralRegisters (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
)
{
UINTN i;
CHAR8 *InBufPtr; /// pointer to the input buffer
UINTN MinLength;
UINTN RegisterCount = MaxRegisterCount();
MinLength = (RegisterCount * 8) + 1; // 'G' plus the registers in ASCII format
if (AsciiStrLen(InBuffer) < MinLength) {
//Bad message. Message is not the right length
SendError (GDB_EBADBUFSIZE);
return;
}
InBufPtr = &InBuffer[1];
// Read the new values for the registers from the input buffer to an array, NewValueArray.
// The values in the array are in the gdb ordering
for(i = 0; i < RegisterCount; i++) {
InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);
}
SendSuccess ();
}
// What about Thumb?
// Use SWI 0xdbdbdb as the debug instruction
#define GDB_ARM_BKPT 0xefdbdbdb
BOOLEAN mSingleStepActive = FALSE;
UINT32 mSingleStepPC;
UINT32 mSingleStepData;
UINTN mSingleStepDataSize;
typedef struct {
LIST_ENTRY Link;
UINT64 Signature;
UINT32 Address;
UINT32 Instruction;
} ARM_SOFTWARE_BREAKPOINT;
#define ARM_SOFTWARE_BREAKPOINT_SIGNATURE SIGNATURE_64('A', 'R', 'M', 'B', 'R', 'K', 'P', 'T')
#define ARM_SOFTWARE_BREAKPOINT_FROM_LINK(a) CR(a, ARM_SOFTWARE_BREAKPOINT, Link, ARM_SOFTWARE_BREAKPOINT_SIGNATURE)
LIST_ENTRY BreakpointList;
/**
Insert Single Step in the SystemContext
@param SystemContext Register content at time of the exception
**/
VOID
AddSingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
if (mSingleStepActive) {
// Currently don't support nesting
return;
}
mSingleStepActive = TRUE;
mSingleStepPC = SystemContext.SystemContextArm->PC;
mSingleStepDataSize = sizeof (UINT32);
mSingleStepData = (*(UINT32 *)mSingleStepPC);
*(UINT32 *)mSingleStepPC = GDB_ARM_BKPT;
if (*(UINT32 *)mSingleStepPC != GDB_ARM_BKPT) {
// For some reason our breakpoint did not take
mSingleStepActive = FALSE;
}
InvalidateInstructionCacheRange((VOID *)mSingleStepPC, mSingleStepDataSize);
//DEBUG((EFI_D_ERROR, "AddSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, mSingleStepData, *(UINT32 *)mSingleStepPC));
}
/**
Remove Single Step in the SystemContext
@param SystemContext Register content at time of the exception
**/
VOID
RemoveSingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
if (!mSingleStepActive) {
return;
}
if (mSingleStepDataSize == sizeof (UINT16)) {
*(UINT16 *)mSingleStepPC = (UINT16)mSingleStepData;
} else {
//DEBUG((EFI_D_ERROR, "RemoveSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, *(UINT32 *)mSingleStepPC, mSingleStepData));
*(UINT32 *)mSingleStepPC = mSingleStepData;
}
InvalidateInstructionCacheRange((VOID *)mSingleStepPC, mSingleStepDataSize);
mSingleStepActive = FALSE;
}
/** c [addr ]
Continue. addr is Address to resume. If addr is omitted, resume at current
Address.
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
ContinueAtAddress (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
if (PacketData[1] != '\0') {
SystemContext.SystemContextArm->PC = AsciiStrHexToUintn(&PacketData[1]);
}
}
/** s [addr ]
Single step. addr is the Address at which to resume. If addr is omitted, resume
at same Address.
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
SingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
SendNotSupported();
}
UINTN
GetBreakpointDataAddress (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN BreakpointNumber
)
{
return 0;
}
UINTN
GetBreakpointDetected (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
return 0;
}
BREAK_TYPE
GetBreakpointType (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN BreakpointNumber
)
{
return NotSupported;
}
ARM_SOFTWARE_BREAKPOINT *
SearchBreakpointList (
IN UINT32 Address
)
{
LIST_ENTRY *Current;
ARM_SOFTWARE_BREAKPOINT *Breakpoint;
Current = GetFirstNode(&BreakpointList);
while (!IsNull(&BreakpointList, Current)) {
Breakpoint = ARM_SOFTWARE_BREAKPOINT_FROM_LINK(Current);
if (Address == Breakpoint->Address) {
return Breakpoint;
}
Current = GetNextNode(&BreakpointList, Current);
}
return NULL;
}
VOID
SetBreakpoint (
IN UINT32 Address
)
{
ARM_SOFTWARE_BREAKPOINT *Breakpoint;
Breakpoint = SearchBreakpointList(Address);
if (Breakpoint != NULL) {
return;
}
// create and fill breakpoint structure
Breakpoint = AllocatePool(sizeof(ARM_SOFTWARE_BREAKPOINT));
Breakpoint->Signature = ARM_SOFTWARE_BREAKPOINT_SIGNATURE;
Breakpoint->Address = Address;
Breakpoint->Instruction = *(UINT32 *)Address;
// Add it to the list
InsertTailList(&BreakpointList, &Breakpoint->Link);
// Insert the software breakpoint
*(UINT32 *)Address = GDB_ARM_BKPT;
InvalidateInstructionCacheRange((VOID *)Address, 4);
//DEBUG((EFI_D_ERROR, "SetBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, Breakpoint->Instruction, *(UINT32 *)Address));
}
VOID
ClearBreakpoint (
IN UINT32 Address
)
{
ARM_SOFTWARE_BREAKPOINT *Breakpoint;
Breakpoint = SearchBreakpointList(Address);
if (Breakpoint == NULL) {
return;
}
// Add it to the list
RemoveEntryList(&Breakpoint->Link);
// Restore the original instruction
*(UINT32 *)Address = Breakpoint->Instruction;
InvalidateInstructionCacheRange((VOID *)Address, 4);
//DEBUG((EFI_D_ERROR, "ClearBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, GDB_ARM_BKPT, *(UINT32 *)Address));
FreePool(Breakpoint);
}
VOID
EFIAPI
InsertBreakPoint (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
UINTN Type;
UINTN Address;
UINTN Length;
UINTN ErrorCode;
ErrorCode = ParseBreakpointPacket(PacketData, &Type, &Address, &Length);
if (ErrorCode > 0) {
SendError ((UINT8)ErrorCode);
return;
}
switch (Type) {
case 0: //Software breakpoint
break;
default :
DEBUG((EFI_D_ERROR, "Insert breakpoint default: %x\n", Type));
SendError (GDB_EINVALIDBRKPOINTTYPE);
return;
}
SetBreakpoint(Address);
SendSuccess ();
}
VOID
EFIAPI
RemoveBreakPoint (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
UINTN Type;
UINTN Address;
UINTN Length;
UINTN ErrorCode;
//Parse breakpoint packet data
ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
if (ErrorCode > 0) {
SendError ((UINT8)ErrorCode);
return;
}
switch (Type) {
case 0: //Software breakpoint
break;
default:
SendError (GDB_EINVALIDBRKPOINTTYPE);
return;
}
ClearBreakpoint(Address);
SendSuccess ();
}
VOID
InitializeProcessor (
VOID
)
{
// Initialize breakpoint list
InitializeListHead(&BreakpointList);
}
BOOLEAN
ValidateAddress (
IN VOID *Address
)
{
if ((UINT32)Address < 0x80000000) {
return FALSE;
} else {
return TRUE;
}
}
BOOLEAN
ValidateException (
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext
)
{
UINT32 ExceptionAddress;
UINT32 Instruction;
// Is it a debugger SWI?
ExceptionAddress = SystemContext.SystemContextArm->PC -= 4;
Instruction = *(UINT32 *)ExceptionAddress;
if (Instruction != GDB_ARM_BKPT) {
return FALSE;
}
// Special for SWI-based exception handling. SWI sets up the context
// to return to the instruction following the SWI instruction - NOT what we want
// for a debugger!
SystemContext.SystemContextArm->PC = ExceptionAddress;
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,78 @@
#%HEADER%
#/** @file
# UEFI GDB stub
#
# This is a shell application that will display Hello World.
# Copyright (c) 2008, Apple, Inc.
#
# 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 = GdbStub
FILE_GUID = 1F2CCB4F-D817-404E-98E7-80E4851FB33E
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = GdbStubEntry
[Sources.common]
GdbStub.c
SerialIo.c
[Sources.ARM]
Arm/Processor.c
[Sources.IA32]
Ia32/Processor.c
[Sources.X64]
X64/Processor.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
BaseLib
DebugLib
UefiLib
UefiDriverEntryPoint
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
BaseMemoryLib
MemoryAllocationLib
DevicePathLib
PcdLib
GdbSerialLib
PrintLib
CacheMaintenanceLib
[Protocols]
gEfiDebugSupportProtocolGuid
gEfiDebugPortProtocolGuid
gEfiSerialIoProtocolGuid
[Guids]
gEfiDebugImageInfoTableGuid
[FeaturePcd.common]
gEmbeddedTokenSpaceGuid.PcdGdbSerial
[FixedPcd.common]
gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount

View File

@@ -0,0 +1,746 @@
/** @file
Private include file for GDB stub
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 __GDB_STUB_INTERNAL__
#define __GDB_STUB_INTERNAL__
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/PcdLib.h>
#include <Library/GdbSerialLib.h>
#include <Library/PrintLib.h>
#include <Protocol/DebugSupport.h>
#include <Protocol/SerialIo.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/LoadedImage.h>
#include <Guid/DebugImageInfoTable.h>
#include <IndustryStandard/PeImage.h>
extern CONST CHAR8 mHexToStr[];
// maximum size of input and output buffers
// This value came from the show remote command of the gdb we tested against
#define MAX_BUF_SIZE 2000
// maximum size of address buffer
#define MAX_ADDR_SIZE 32
// maximum size of register number buffer
#define MAX_REG_NUM_BUF_SIZE 32
// maximum size of length buffer
#define MAX_LENGTH_SIZE 32
// maximum size of T signal members
#define MAX_T_SIGNAL_SIZE 64
// the mask used to clear all the cache
#define TF_BIT 0x00000100
//
// GDB Signal definitions - generic names for interrupts
//
#define GDB_SIGILL 4 // Illegal instruction
#define GDB_SIGTRAP 5 // Trace Trap (Breakpoint and SingleStep)
#define GDB_SIGEMT 7 // Emulator Trap
#define GDB_SIGFPE 8 // Floating point exception
#define GDB_SIGSEGV 11 // Setgment violation, page fault
//
// GDB File I/O Error values, zero means no error
// Includes all general GDB Unix like error values
//
#define GDB_EBADMEMADDRBUFSIZE 11 // the buffer that stores memory Address to be read from/written to is not the right size
#define GDB_EBADMEMLENGBUFSIZE 12 // the buffer that stores Length is not the right size
#define GDB_EBADMEMLENGTH 13 // Length, the given number of bytes to read or write, is not the right size
#define GDB_EBADMEMDATA 14 // one of the bytes or nibbles of the memory is leess than 0
#define GDB_EBADMEMDATASIZE 15 // the memory data, 'XX..', is too short or too long
#define GDB_EBADBUFSIZE 21 // the buffer created is not the correct size
#define GDB_EINVALIDARG 31 // argument is invalid
#define GDB_ENOSPACE 41 //
#define GDB_EINVALIDBRKPOINTTYPE 51 // the breakpoint type is not recognized
#define GDB_EINVALIDREGNUM 61 // given register number is not valid: either <0 or >=Number of Registers
#define GDB_EUNKNOWN 255 // unknown
//
// These devices are open by GDB so we can just read and write to them
//
#define GDB_STDIN 0x00
#define GDB_STDOUT 0x01
#define GDB_STDERR 0x02
//
//Define Register size for different architectures
//
#if defined (MDE_CPU_IA32)
#define REG_SIZE 32
#elif defined (MDE_CPU_X64)
#define REG_SIZE 64
#elif defined (MDE_CPU_ARM)
#define REG_SIZE 32
#endif
#define GDB_SERIAL_DEV_SIGNATURE SIGNATURE_32 ('g', 'd', 'b', 's')
typedef struct {
VENDOR_DEVICE_PATH VendorDevice;
UINT32 Index; // Suport more than one
EFI_DEVICE_PATH_PROTOCOL End;
} GDB_SERIAL_DEVICE_PATH;
//
// Name: SERIAL_DEV
// Purpose: To provide device specific information
// Fields:
// Signature UINTN: The identity of the serial device
// SerialIo SERIAL_IO_PROTOCOL: Serial I/O protocol interface
// SerialMode SERIAL_IO_MODE:
// DevicePath EFI_DEVICE_PATH_PROTOCOL *: Device path of the serial device
//
typedef struct {
UINTN Signature;
EFI_HANDLE Handle;
EFI_SERIAL_IO_PROTOCOL SerialIo;
EFI_SERIAL_IO_MODE SerialMode;
GDB_SERIAL_DEVICE_PATH DevicePath;
INTN InFileDescriptor;
INTN OutFileDescriptor;
} GDB_SERIAL_DEV;
#define GDB_SERIAL_DEV_FROM_THIS(a) CR (a, GDB_SERIAL_DEV, SerialIo, GDB_SERIAL_DEV_SIGNATURE)
typedef struct {
EFI_EXCEPTION_TYPE Exception;
UINT8 SignalNo;
} EFI_EXCEPTION_TYPE_ENTRY;
#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
//
// Byte packed structure for DR6
// 32-bits on IA-32
// 64-bits on X64. The upper 32-bits on X64 are reserved
//
typedef union {
struct {
UINT32 B0:1; // Breakpoint condition detected
UINT32 B1:1; // Breakpoint condition detected
UINT32 B2:1; // Breakpoint condition detected
UINT32 B3:1; // Breakpoint condition detected
UINT32 Reserved_1:9; // Reserved
UINT32 BD:1; // Debug register access detected
UINT32 BS:1; // Single step
UINT32 BT:1; // Task switch
UINT32 Reserved_2:16; // Reserved
} Bits;
UINTN UintN;
} IA32_DR6;
//
// Byte packed structure for DR7
// 32-bits on IA-32
// 64-bits on X64. The upper 32-bits on X64 are reserved
//
typedef union {
struct {
UINT32 L0:1; // Local breakpoint enable
UINT32 G0:1; // Global breakpoint enable
UINT32 L1:1; // Local breakpoint enable
UINT32 G1:1; // Global breakpoint enable
UINT32 L2:1; // Local breakpoint enable
UINT32 G2:1; // Global breakpoint enable
UINT32 L3:1; // Local breakpoint enable
UINT32 G3:1; // Global breakpoint enable
UINT32 LE:1; // Local exact breakpoint enable
UINT32 GE:1; // Global exact breakpoint enable
UINT32 Reserved_1:3; // Reserved
UINT32 GD:1; // Global detect enable
UINT32 Reserved_2:2; // Reserved
UINT32 RW0:2; // Read/Write field
UINT32 LEN0:2; // Length field
UINT32 RW1:2; // Read/Write field
UINT32 LEN1:2; // Length field
UINT32 RW2:2; // Read/Write field
UINT32 LEN2:2; // Length field
UINT32 RW3:2; // Read/Write field
UINT32 LEN3:2; // Length field
} Bits;
UINTN UintN;
} IA32_DR7;
#endif /* if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) */
typedef enum {
InstructionExecution, //Hardware breakpoint
DataWrite, //watch
DataRead, //rwatch
DataReadWrite, //awatch
SoftwareBreakpoint, //Software breakpoint
NotSupported
} BREAK_TYPE;
//
// Array of exception types that need to be hooked by the debugger
//
extern EFI_EXCEPTION_TYPE_ENTRY gExceptionType[];
//
// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c
// here we need to wait for the periodic callback to do this.
//
extern BOOLEAN gCtrlCBreakFlag;
//
// If the periodic callback is called while we are processing an F packet we need
// to let the callback know to not read from the serail stream as it could steal
// characters from the F reponse packet
//
extern BOOLEAN gProcessingFPacket;
// The offsets of registers SystemContext.
// The fields in the array are in the gdb ordering.
//
extern UINTN gRegisterOffsets[];
/**
Return the number of entries in the gExceptionType[]
@retval UINTN, the number of entries in the gExceptionType[] array.
**/
UINTN
MaxEfiException (
VOID
);
/**
Return the number of entries in the gRegisters[]
@retval UINTN, the number of entries (registers) in the gRegisters[] array.
**/
UINTN
MaxRegisterCount (
VOID
);
/**
Check to see if the ISA is supported.
ISA = Instruction Set Architecture
@retval TRUE if Isa is supported,
FALSE otherwise.
**/
BOOLEAN
CheckIsa (
IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
);
/**
Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints
@param SystemContext Register content at time of the exception
@param GdbExceptionType GDB exception type
**/
VOID
GdbSendTSignal (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINT8 GdbExceptionType
);
/**
Translates the EFI mapping to GDB mapping
@param EFIExceptionType EFI Exception that is being processed
@retval UINTN that corresponds to EFIExceptionType's GDB exception type number
**/
UINT8
ConvertEFItoGDBtype (
IN EFI_EXCEPTION_TYPE EFIExceptionType
);
/**
Empties the given buffer
@param *Buf pointer to the first element in buffer to be emptied
**/
VOID
EmptyBuffer (
IN CHAR8 *Buf
);
/**
Converts an 8-bit Hex Char into a INTN.
@param Char - the hex character to be converted into UINTN
@retval a INTN, from 0 to 15, that corressponds to Char
-1 if Char is not a hex character
**/
INTN
HexCharToInt (
IN CHAR8 Char
);
/** 'E NN'
Send an error with the given error number after converting to hex.
The error number is put into the buffer in hex. '255' is the biggest errno we can send.
ex: 162 will be sent as A2.
@param errno the error number that will be sent
**/
VOID
EFIAPI
SendError (
IN UINT8 ErrorNum
);
/**
Send 'OK' when the function is done executing successfully.
**/
VOID
SendSuccess (
VOID
);
/**
Send empty packet to specify that particular command/functionality is not supported.
**/
VOID
SendNotSupported (
VOID
);
/** p n
Reads the n-th register's value into an output buffer and sends it as a packet
@param SystemContext Register content at time of the exception
@param InBuffer This is the input buffer received from gdb server
**/
VOID
ReadNthRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
);
/** g
Reads the general registers into an output buffer and sends it as a packet
@param SystemContext Register content at time of the exception
**/
VOID
ReadGeneralRegisters (
IN EFI_SYSTEM_CONTEXT SystemContext
);
/** P n...=r...
Writes the new value of n-th register received into the input buffer to the n-th register
@param SystemContext Register content at time of the exception
@param InBuffer This is the input buffer received from gdb server
**/
VOID
WriteNthRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
);
/** G XX...
Writes the new values received into the input buffer to the general registers
@param SystemContext Register content at time of the exception
@param InBuffer Pointer to the input buffer received from gdb server
**/
VOID
WriteGeneralRegisters (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
);
/** m addr,length
Find the Length of the area to read and the start addres. Finally, pass them to
another function, TransferFromMemToOutBufAndSend, that will read from that memory space and
send it as a packet.
@param *PacketData Pointer to Payload data for the packet
**/
VOID
ReadFromMemory (
IN CHAR8 *PacketData
);
/** M addr,length :XX...
Find the Length of the area in bytes to write and the start addres. Finally, pass them to
another function, TransferFromInBufToMem, that will write to that memory space the info in
the input buffer.
@param PacketData Pointer to Payload data for the packet
**/
VOID
WriteToMemory (
IN CHAR8 *PacketData
);
/** c [addr ]
Continue. addr is Address to resume. If addr is omitted, resume at current
Address.
@param SystemContext Register content at time of the exception
@param *PacketData Pointer to PacketData
**/
VOID
ContinueAtAddress (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
);
/** s [addr ]
Single step. addr is the Address at which to resume. If addr is omitted, resume
at same Address.
@param SystemContext Register content at time of the exception
@param PacketData Pointer to Payload data for the packet
**/
VOID
SingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
);
/**
Insert Single Step in the SystemContext
@param SystemContext Register content at time of the exception
**/
VOID
AddSingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext
);
/**
Remove Single Step in the SystemContext
@param SystemContext Register content at time of the exception
**/
VOID
RemoveSingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext
);
/**
Z1, [addr], [length]
Z2, [addr], [length]
Z3, [addr], [length]
Z4, [addr], [length]
Insert hardware breakpoint/watchpoint at address addr of size length
@param SystemContext Register content at time of the exception
@param *PacketData Pointer to the Payload data for the packet
**/
VOID
EFIAPI
InsertBreakPoint(
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
);
/**
z1, [addr], [length]
z2, [addr], [length]
z3, [addr], [length]
z4, [addr], [length]
Remove hardware breakpoint/watchpoint at address addr of size length
@param SystemContext Register content at time of the exception
@param *PacketData Pointer to the Payload data for the packet
**/
VOID
EFIAPI
RemoveBreakPoint(
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
);
/**
Exception Hanldler for GDB. It will be called for all exceptions
registered via the gExceptionType[] array.
@param ExceptionType Exception that is being processed
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
GdbExceptionHandler (
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext
);
/**
Periodic callback for GDB. This function is used to catch a ctrl-c or other
break in type command from GDB.
@param SystemContext Register content at time of the call
**/
VOID
EFIAPI
GdbPeriodicCallBack (
IN OUT EFI_SYSTEM_CONTEXT SystemContext
);
/**
Make two serail consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.
These console show up on the remote system running GDB
**/
VOID
GdbInitializeSerialConsole (
VOID
);
/**
Send a GDB Remote Serial Protocol Packet
$PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
the packet teminating character '#' and the two digit checksum.
If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up
in an infinit loop. This is so if you unplug the debugger code just keeps running
@param PacketData Payload data for the packet
@retval Number of bytes of packet data sent.
**/
UINTN
SendPacket (
IN CHAR8 *PacketData
);
/**
Receive a GDB Remote Serial Protocol Packet
$PacketData#checksum PacketData is passed in and this function adds the packet prefix '$',
the packet teminating character '#' and the two digit checksum.
If host re-starts sending a packet without ending the previous packet, only the last valid packet is proccessed.
(In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.)
If an ack '+' is not sent resend the packet
@param PacketData Payload data for the packet
@retval Number of bytes of packet data received.
**/
UINTN
ReceivePacket (
OUT CHAR8 *PacketData,
IN UINTN PacketDataSize
);
/**
Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates
the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.
@param FileDescriptor Device to talk to.
@param Buffer Buffer to hold Count bytes that were read
@param Count Number of bytes to transfer.
@retval -1 Error
@retval {other} Number of bytes read.
**/
INTN
GdbRead (
IN INTN FileDescriptor,
OUT VOID *Buffer,
IN UINTN Count
);
/**
Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates
nothing was written. On error -1 is returned.
@param FileDescriptor Device to talk to.
@param Buffer Buffer to hold Count bytes that are to be written
@param Count Number of bytes to transfer.
@retval -1 Error
@retval {other} Number of bytes written.
**/
INTN
GdbWrite (
IN INTN FileDescriptor,
OUT CONST VOID *Buffer,
IN UINTN Count
);
UINTN *
FindPointerToRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber
);
CHAR8 *
BasicReadRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber,
IN CHAR8 *OutBufPtr
);
VOID
TransferFromInBufToMem (
IN UINTN Length,
IN UINT8 *Address,
IN CHAR8 *NewData
);
VOID
TransferFromMemToOutBufAndSend (
IN UINTN Length,
IN UINT8 *Address
);
CHAR8 *
BasicWriteRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber,
IN CHAR8 *InBufPtr
);
VOID
PrintReg (
EFI_SYSTEM_CONTEXT SystemContext
);
UINTN
ParseBreakpointPacket (
IN CHAR8 *PacketData,
OUT UINTN *Type,
OUT UINTN *Address,
OUT UINTN *Length
);
UINTN
GetBreakpointDataAddress (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN BreakpointNumber
);
UINTN
GetBreakpointDetected (
IN EFI_SYSTEM_CONTEXT SystemContext
);
BREAK_TYPE
GetBreakpointType (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN BreakpointNumber
);
UINTN
ConvertLengthData (
IN UINTN Length
);
EFI_STATUS
FindNextFreeDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
OUT UINTN *Register
);
EFI_STATUS
EnableDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN Register,
IN UINTN Address,
IN UINTN Length,
IN UINTN Type
);
EFI_STATUS
FindMatchingDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN Address,
IN UINTN Length,
IN UINTN Type,
OUT UINTN *Register
);
EFI_STATUS
DisableDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN Register
);
VOID
InitializeProcessor (
VOID
);
BOOLEAN
ValidateAddress (
IN VOID *Address
);
BOOLEAN
ValidateException (
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext
);
#endif

View File

@@ -0,0 +1,993 @@
/** @file
Processor specific parts of the GDB stub
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 <GdbStubInternal.h>
//
// Array of exception types that need to be hooked by the debugger
// {EFI mapping, GDB mapping}
//
EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
{ EXCEPT_IA32_DIVIDE_ERROR, GDB_SIGFPE },
{ EXCEPT_IA32_DEBUG, GDB_SIGTRAP },
{ EXCEPT_IA32_NMI, GDB_SIGEMT },
{ EXCEPT_IA32_BREAKPOINT, GDB_SIGTRAP },
{ EXCEPT_IA32_OVERFLOW, GDB_SIGSEGV },
{ EXCEPT_IA32_BOUND, GDB_SIGSEGV },
{ EXCEPT_IA32_INVALID_OPCODE, GDB_SIGILL },
{ EXCEPT_IA32_DOUBLE_FAULT, GDB_SIGEMT },
{ EXCEPT_IA32_STACK_FAULT, GDB_SIGSEGV },
{ EXCEPT_IA32_GP_FAULT, GDB_SIGSEGV },
{ EXCEPT_IA32_PAGE_FAULT, GDB_SIGSEGV },
{ EXCEPT_IA32_FP_ERROR, GDB_SIGEMT },
{ EXCEPT_IA32_ALIGNMENT_CHECK, GDB_SIGEMT },
{ EXCEPT_IA32_MACHINE_CHECK, GDB_SIGEMT }
};
// The offsets of registers SystemContext.
// The fields in the array are in the gdb ordering.
//
//16 regs
UINTN gRegisterOffsets[] = {
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eax),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ecx),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edx),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebx),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esp),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebp),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esi),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edi),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eip),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eflags),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Cs),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ss),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ds),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Es),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Fs),
OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Gs)
};
//Debug only..
VOID
PrintReg (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
Print ((CHAR16 *)L"EAX: %x ", SystemContext.SystemContextIa32->Eax);
Print ((CHAR16 *)L"ECX: %x ", SystemContext.SystemContextIa32->Ecx);
Print ((CHAR16 *)L"EDX: %x ", SystemContext.SystemContextIa32->Edx);
Print ((CHAR16 *)L"EBX: %x ", SystemContext.SystemContextIa32->Ebx);
Print ((CHAR16 *)L"ESP: %x ", SystemContext.SystemContextIa32->Esp);
Print ((CHAR16 *)L"EBP: %x ", SystemContext.SystemContextIa32->Ebp);
Print ((CHAR16 *)L"ESI: %x ", SystemContext.SystemContextIa32->Esi);
Print ((CHAR16 *)L"EDI: %x ", SystemContext.SystemContextIa32->Edi);
Print ((CHAR16 *)L"EIP: %x\n", SystemContext.SystemContextIa32->Eip);
Print ((CHAR16 *)L"EFlags: %x\n", SystemContext.SystemContextIa32->Eflags);
}
//Debug only..
VOID
PrintDRreg (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
Print ((CHAR16 *)L"DR0: %x ", SystemContext.SystemContextIa32->Dr0);
Print ((CHAR16 *)L"DR1: %x ", SystemContext.SystemContextIa32->Dr1);
Print ((CHAR16 *)L"DR2: %x ", SystemContext.SystemContextIa32->Dr2);
Print ((CHAR16 *)L"DR3: %x ", SystemContext.SystemContextIa32->Dr3);
Print ((CHAR16 *)L"DR6: %x ", SystemContext.SystemContextIa32->Dr6);
Print ((CHAR16 *)L"DR7: %x\n", SystemContext.SystemContextIa32->Dr7);
}
/**
Return the number of entries in the gExceptionType[]
@retval UINTN, the number of entries in the gExceptionType[] array.
**/
UINTN
MaxEfiException (
VOID
)
{
return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
}
/**
Return the number of entries in the gRegisters[]
@retval UINTN, the number of entries (registers) in the gRegisters[] array.
**/
UINTN
MaxRegisterCount (
VOID
)
{
return sizeof (gRegisterOffsets)/sizeof (UINTN);
}
/**
Check to see if the ISA is supported.
ISA = Instruction Set Architecture
@retval TRUE if Isa is supported,
FALSE otherwise.
**/
BOOLEAN
CheckIsa (
IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
)
{
return (BOOLEAN)(Isa == IsaIa32);
}
/**
This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
It is, by default, set to find the register pointer of the IA32 member
@param SystemContext Register content at time of the exception
@param RegNumber The register to which we want to find a pointer
@retval the pointer to the RegNumber-th pointer
**/
UINTN *
FindPointerToRegister(
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber
)
{
UINT8 *TempPtr;
TempPtr = ((UINT8 *)SystemContext.SystemContextIa32) + gRegisterOffsets[RegNumber];
return (UINTN *)TempPtr;
}
/**
Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
@param SystemContext Register content at time of the exception
@param RegNumber the number of the register that we want to read
@param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
@retval the pointer to the next character of the output buffer that is available to be written on.
**/
CHAR8 *
BasicReadRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber,
IN CHAR8 *OutBufPtr
)
{
UINTN RegSize;
RegSize = 0;
while (RegSize < REG_SIZE) {
*OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
*OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];
RegSize = RegSize + 8;
}
return OutBufPtr;
}
/** p n
Reads the n-th register's value into an output buffer and sends it as a packet
@param SystemContext Register content at time of the exception
@param InBuffer Pointer to the input buffer received from gdb server
**/
VOID
EFIAPI
ReadNthRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
)
{
UINTN RegNumber;
CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
CHAR8 *OutBufPtr; // pointer to the output buffer
RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {
SendError (GDB_EINVALIDREGNUM);
return;
}
OutBufPtr = OutBuffer;
OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr);
*OutBufPtr = '\0'; // the end of the buffer
SendPacket(OutBuffer);
}
/** g
Reads the general registers into an output buffer and sends it as a packet
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
ReadGeneralRegisters (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
UINTN i;
CHAR8 OutBuffer[129]; // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
CHAR8 *OutBufPtr; // pointer to the output buffer
OutBufPtr = OutBuffer;
for(i = 0 ; i < MaxRegisterCount() ; i++) { // there are only 16 registers to read
OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr);
}
*OutBufPtr = '\0'; // the end of the buffer
SendPacket(OutBuffer);
}
/**
Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
@param SystemContext Register content at time of the exception
@param RegNumber the number of the register that we want to write
@param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
@retval the pointer to the next character of the input buffer that can be used
**/
CHAR8 *
BasicWriteRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber,
IN CHAR8 *InBufPtr
)
{
UINTN RegSize;
UINTN TempValue; // the value transferred from a hex char
UINT32 NewValue; // the new value of the RegNumber-th Register
NewValue = 0;
RegSize = 0;
while (RegSize < REG_SIZE) {
TempValue = HexCharToInt(*InBufPtr++);
if (TempValue < 0) {
SendError (GDB_EBADMEMDATA);
return NULL;
}
NewValue += (TempValue << (RegSize+4));
TempValue = HexCharToInt(*InBufPtr++);
if (TempValue < 0) {
SendError (GDB_EBADMEMDATA);
return NULL;
}
NewValue += (TempValue << RegSize);
RegSize = RegSize + 8;
}
*(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;
return InBufPtr;
}
/** P n...=r...
Writes the new value of n-th register received into the input buffer to the n-th register
@param SystemContext Register content at time of the exception
@param InBuffer Ponter to the input buffer received from gdb server
**/
VOID
EFIAPI
WriteNthRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
)
{
UINTN RegNumber;
CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
CHAR8 *RegNumBufPtr;
CHAR8 *InBufPtr; // pointer to the input buffer
// find the register number to write
InBufPtr = &InBuffer[1];
RegNumBufPtr = RegNumBuffer;
while (*InBufPtr != '=') {
*RegNumBufPtr++ = *InBufPtr++;
}
*RegNumBufPtr = '\0';
RegNumber = AsciiStrHexToUintn (RegNumBuffer);
// check if this is a valid Register Number
if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {
SendError (GDB_EINVALIDREGNUM);
return;
}
InBufPtr++; // skips the '=' character
BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
SendSuccess();
}
/** G XX...
Writes the new values received into the input buffer to the general registers
@param SystemContext Register content at time of the exception
@param InBuffer Pointer to the input buffer received from gdb server
**/
VOID
EFIAPI
WriteGeneralRegisters (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
)
{
UINTN i;
CHAR8 *InBufPtr; /// pointer to the input buffer
// check to see if the buffer is the right size which is
// 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 129
if (AsciiStrLen(InBuffer) != 129) { // 16 regs, 8 hex chars each, and the end '\0' (escape seq)
//Bad message. Message is not the right length
SendError (GDB_EBADBUFSIZE);
return;
}
InBufPtr = &InBuffer[1];
// Read the new values for the registers from the input buffer to an array, NewValueArray.
// The values in the array are in the gdb ordering
for(i=0; i < MaxRegisterCount(); i++) { // there are only 16 registers to write
InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr);
}
SendSuccess();
}
/**
Insert Single Step in the SystemContext
@param SystemContext Register content at time of the exception
**/
VOID
AddSingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
SystemContext.SystemContextIa32->Eflags |= TF_BIT; //Setting the TF bit.
}
/**
Remove Single Step in the SystemContext
@param SystemContext Register content at time of the exception
**/
VOID
RemoveSingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
SystemContext.SystemContextIa32->Eflags &= ~TF_BIT; // clearing the TF bit.
}
/** c [addr ]
Continue. addr is Address to resume. If addr is omitted, resume at current
Address.
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
ContinueAtAddress (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
if (PacketData[1] != '\0') {
SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]);
}
}
/** s [addr ]
Single step. addr is the Address at which to resume. If addr is omitted, resume
at same Address.
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
SingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
if (PacketData[1] != '\0') {
SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]);
}
AddSingleStep (SystemContext);
}
/**
Returns breakpoint data address from DR0-DR3 based on the input breakpoint number
@param SystemContext Register content at time of the exception
@param BreakpointNumber Breakpoint number
@retval Address Data address from DR0-DR3 based on the breakpoint number.
**/
UINTN
GetBreakpointDataAddress (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN BreakpointNumber
)
{
UINTN Address;
if (BreakpointNumber == 1) {
Address = SystemContext.SystemContextIa32->Dr0;
} else if (BreakpointNumber == 2) {
Address = SystemContext.SystemContextIa32->Dr1;
} else if (BreakpointNumber == 3) {
Address = SystemContext.SystemContextIa32->Dr2;
} else if (BreakpointNumber == 4) {
Address = SystemContext.SystemContextIa32->Dr3;
} else {
Address = 0;
}
return Address;
}
/**
Returns currently detected breakpoint value based on the register DR6 B0-B3 field.
If no breakpoint is detected then it returns 0.
@param SystemContext Register content at time of the exception
@retval {1-4} Currently detected breakpoint value
@retval 0 No breakpoint detected.
**/
UINTN
GetBreakpointDetected (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
IA32_DR6 Dr6;
UINTN BreakpointNumber;
Dr6.UintN = SystemContext.SystemContextIa32->Dr6;
if (Dr6.Bits.B0 == 1) {
BreakpointNumber = 1;
} else if (Dr6.Bits.B1 == 1) {
BreakpointNumber = 2;
} else if (Dr6.Bits.B2 == 1) {
BreakpointNumber = 3;
} else if (Dr6.Bits.B3 == 1) {
BreakpointNumber = 4;
} else {
BreakpointNumber = 0; //No breakpoint detected
}
return BreakpointNumber;
}
/**
Returns Breakpoint type (InstructionExecution, DataWrite, DataRead or DataReadWrite)
based on the Breakpoint number
@param SystemContext Register content at time of the exception
@param BreakpointNumber Breakpoint number
@retval BREAK_TYPE Breakpoint type value read from register DR7 RWn field
For unknown value, it returns NotSupported.
**/
BREAK_TYPE
GetBreakpointType (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN BreakpointNumber
)
{
IA32_DR7 Dr7;
BREAK_TYPE Type = NotSupported; //Default is NotSupported type
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if (BreakpointNumber == 1) {
Type = (BREAK_TYPE) Dr7.Bits.RW0;
} else if (BreakpointNumber == 2) {
Type = (BREAK_TYPE) Dr7.Bits.RW1;
} else if (BreakpointNumber == 3) {
Type = (BREAK_TYPE) Dr7.Bits.RW2;
} else if (BreakpointNumber == 4) {
Type = (BREAK_TYPE) Dr7.Bits.RW3;
}
return Type;
}
/**
Parses Length and returns the length which DR7 LENn field accepts.
For example: If we receive 1-Byte length then we should return 0.
Zero gets written to DR7 LENn field.
@param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
@retval Length Appropriate converted values which DR7 LENn field accepts.
**/
UINTN
ConvertLengthData (
IN UINTN Length
)
{
if (Length == 1) { //1-Byte length
return 0;
} else if (Length == 2) { //2-Byte length
return 1;
} else if (Length == 4) { //4-Byte length
return 3;
} else { //Undefined or 8-byte length
return 2;
}
}
/**
Finds the next free debug register. If all the registers are occupied then
EFI_OUT_OF_RESOURCES is returned.
@param SystemContext Register content at time of the exception
@param Register Register value (0 - 3 for the first free debug register)
@retval EFI_STATUS Appropriate status value.
**/
EFI_STATUS
FindNextFreeDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
OUT UINTN *Register
)
{
IA32_DR7 Dr7;
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if (Dr7.Bits.G0 == 0) {
*Register = 0;
} else if (Dr7.Bits.G1 == 0) {
*Register = 1;
} else if (Dr7.Bits.G2 == 0) {
*Register = 2;
} else if (Dr7.Bits.G3 == 0) {
*Register = 3;
} else {
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS;
}
/**
Enables the debug register. Writes Address value to appropriate DR0-3 register.
Sets LENn, Gn, RWn bits in DR7 register.
@param SystemContext Register content at time of the exception
@param Register Register value (0 - 3)
@param Address Breakpoint address value
@param Type Breakpoint type (Instruction, Data write, Data read
or write etc.)
@retval EFI_STATUS Appropriate status value.
**/
EFI_STATUS
EnableDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN Register,
IN UINTN Address,
IN UINTN Length,
IN UINTN Type
)
{
IA32_DR7 Dr7;
//Convert length data
Length = ConvertLengthData (Length);
//For Instruction execution, length should be 0
//(Ref. Intel reference manual 18.2.4)
if ((Type == 0) && (Length != 0)) {
return EFI_INVALID_PARAMETER;
}
//Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
//software breakpoint. We should send empty packet in both these cases.
if ((Type == (BREAK_TYPE)DataRead) ||
(Type == (BREAK_TYPE)SoftwareBreakpoint)) {
return EFI_UNSUPPORTED;
}
//Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if (Register == 0) {
SystemContext.SystemContextIa32->Dr0 = Address;
Dr7.Bits.G0 = 1;
Dr7.Bits.RW0 = Type;
Dr7.Bits.LEN0 = Length;
} else if (Register == 1) {
SystemContext.SystemContextIa32->Dr1 = Address;
Dr7.Bits.G1 = 1;
Dr7.Bits.RW1 = Type;
Dr7.Bits.LEN1 = Length;
} else if (Register == 2) {
SystemContext.SystemContextIa32->Dr2 = Address;
Dr7.Bits.G2 = 1;
Dr7.Bits.RW2 = Type;
Dr7.Bits.LEN2 = Length;
} else if (Register == 3) {
SystemContext.SystemContextIa32->Dr3 = Address;
Dr7.Bits.G3 = 1;
Dr7.Bits.RW3 = Type;
Dr7.Bits.LEN3 = Length;
} else {
return EFI_INVALID_PARAMETER;
}
//Update Dr7 with appropriate Gn, RWn and LENn bits
SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
return EFI_SUCCESS;
}
/**
Returns register number 0 - 3 for the maching debug register.
This function compares incoming Address, Type, Length and
if there is a match then it returns the appropriate register number.
In case of mismatch, function returns EFI_NOT_FOUND message.
@param SystemContext Register content at time of the exception
@param Address Breakpoint address value
@param Length Breakpoint length value
@param Type Breakpoint type (Instruction, Data write,
Data read or write etc.)
@param Register Register value to be returned
@retval EFI_STATUS Appropriate status value.
**/
EFI_STATUS
FindMatchingDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN Address,
IN UINTN Length,
IN UINTN Type,
OUT UINTN *Register
)
{
IA32_DR7 Dr7;
//Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
//software breakpoint. We should send empty packet in both these cases.
if ((Type == (BREAK_TYPE)DataRead) ||
(Type == (BREAK_TYPE)SoftwareBreakpoint)) {
return EFI_UNSUPPORTED;
}
//Convert length data
Length = ConvertLengthData(Length);
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if ((Dr7.Bits.G0 == 1) &&
(Dr7.Bits.LEN0 == Length) &&
(Dr7.Bits.RW0 == Type) &&
(Address == SystemContext.SystemContextIa32->Dr0)) {
*Register = 0;
} else if ((Dr7.Bits.G1 == 1) &&
(Dr7.Bits.LEN1 == Length) &&
(Dr7.Bits.RW1 == Type) &&
(Address == SystemContext.SystemContextIa32->Dr1)) {
*Register = 1;
} else if ((Dr7.Bits.G2 == 1) &&
(Dr7.Bits.LEN2 == Length) &&
(Dr7.Bits.RW2 == Type) &&
(Address == SystemContext.SystemContextIa32->Dr2)) {
*Register = 2;
} else if ((Dr7.Bits.G3 == 1) &&
(Dr7.Bits.LEN3 == Length) &&
(Dr7.Bits.RW3 == Type) &&
(Address == SystemContext.SystemContextIa32->Dr3)) {
*Register = 3;
} else {
Print ((CHAR16 *)L"No match found..\n");
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
/**
Disables the particular debug register.
@param SystemContext Register content at time of the exception
@param Register Register to be disabled
@retval EFI_STATUS Appropriate status value.
**/
EFI_STATUS
DisableDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN Register
)
{
IA32_DR7 Dr7;
UINTN Address = 0;
//Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if (Register == 0) {
SystemContext.SystemContextIa32->Dr0 = Address;
Dr7.Bits.G0 = 0;
Dr7.Bits.RW0 = 0;
Dr7.Bits.LEN0 = 0;
} else if (Register == 1) {
SystemContext.SystemContextIa32->Dr1 = Address;
Dr7.Bits.G1 = 0;
Dr7.Bits.RW1 = 0;
Dr7.Bits.LEN1 = 0;
} else if (Register == 2) {
SystemContext.SystemContextIa32->Dr2 = Address;
Dr7.Bits.G2 = 0;
Dr7.Bits.RW2 = 0;
Dr7.Bits.LEN2 = 0;
} else if (Register == 3) {
SystemContext.SystemContextIa32->Dr3 = Address;
Dr7.Bits.G3 = 0;
Dr7.Bits.RW3 = 0;
Dr7.Bits.LEN3 = 0;
} else {
return EFI_INVALID_PARAMETER;
}
//Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
return EFI_SUCCESS;
}
/**
Z1, [addr], [length]
Z2, [addr], [length]
Z3, [addr], [length]
Z4, [addr], [length]
Insert hardware breakpoint/watchpoint at address addr of size length
@param SystemContext Register content at time of the exception
@param *PacketData Pointer to the Payload data for the packet
**/
VOID
EFIAPI
InsertBreakPoint (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
UINTN Type;
UINTN Address;
UINTN Length;
UINTN Register;
EFI_STATUS Status;
BREAK_TYPE BreakType = NotSupported;
UINTN ErrorCode;
ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
if (ErrorCode > 0) {
SendError ((UINT8)ErrorCode);
return;
}
switch (Type) {
case 0: //Software breakpoint
BreakType = SoftwareBreakpoint;
break;
case 1: //Hardware breakpoint
BreakType = InstructionExecution;
break;
case 2: //Write watchpoint
BreakType = DataWrite;
break;
case 3: //Read watchpoint
BreakType = DataRead;
break;
case 4: //Access watchpoint
BreakType = DataReadWrite;
break;
default :
Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type);
SendError (GDB_EINVALIDBRKPOINTTYPE);
return;
}
// Find next free debug register
Status = FindNextFreeDebugRegister (SystemContext, &Register);
if (EFI_ERROR(Status)) {
Print ((CHAR16 *)L"No space left on device\n");
SendError (GDB_ENOSPACE);
return;
}
// Write Address, length data at particular DR register
Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType);
if (EFI_ERROR(Status)) {
if (Status == EFI_UNSUPPORTED) {
Print ((CHAR16 *)L"Not supported\n");
SendNotSupported();
return;
}
Print ((CHAR16 *)L"Invalid argument\n");
SendError (GDB_EINVALIDARG);
return;
}
SendSuccess ();
}
/**
z1, [addr], [length]
z2, [addr], [length]
z3, [addr], [length]
z4, [addr], [length]
Remove hardware breakpoint/watchpoint at address addr of size length
@param *PacketData Pointer to the Payload data for the packet
**/
VOID
EFIAPI
RemoveBreakPoint (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
UINTN Type;
UINTN Address;
UINTN Length;
UINTN Register;
BREAK_TYPE BreakType = NotSupported;
EFI_STATUS Status;
UINTN ErrorCode;
//Parse breakpoint packet data
ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
if (ErrorCode > 0) {
SendError ((UINT8)ErrorCode);
return;
}
switch (Type) {
case 0: //Software breakpoint
BreakType = SoftwareBreakpoint;
break;
case 1: //Hardware breakpoint
BreakType = InstructionExecution;
break;
case 2: //Write watchpoint
BreakType = DataWrite;
break;
case 3: //Read watchpoint
BreakType = DataRead;
break;
case 4: //Access watchpoint
BreakType = DataReadWrite;
break;
default :
SendError (GDB_EINVALIDBRKPOINTTYPE);
return;
}
//Find matching debug register
Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register);
if (EFI_ERROR(Status)) {
if (Status == EFI_UNSUPPORTED) {
Print ((CHAR16 *)L"Not supported.\n");
SendNotSupported();
return;
}
Print ((CHAR16 *)L"No matching register found.\n");
SendError (GDB_ENOSPACE);
return;
}
//Remove breakpoint
Status = DisableDebugRegister(SystemContext, Register);
if (EFI_ERROR(Status)) {
Print ((CHAR16 *)L"Invalid argument.\n");
SendError (GDB_EINVALIDARG);
return;
}
SendSuccess ();
}
VOID
InitializeProcessor (
VOID
)
{
}
BOOLEAN
ValidateAddress (
IN VOID *Address
)
{
return TRUE;
}
BOOLEAN
ValidateException (
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext
)
{
return TRUE;
}

View File

@@ -0,0 +1,551 @@
/** @file
Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system
running GDB. One consle for error information and another console for user input/output.
Basic packet format is $packet-data#checksum. So every comand has 4 bytes of overhead: $,
#, 0, 0. The 0 and 0 are the ascii characters for the checksum.
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 <GdbStubInternal.h>
//
// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c
// here we need to wait for the periodic callback to do this.
//
BOOLEAN gCtrlCBreakFlag = FALSE;
//
// If the periodic callback is called while we are processing an F packet we need
// to let the callback know to not read from the serail stream as it could steal
// characters from the F reponse packet
//
BOOLEAN gProcessingFPacket = FALSE;
/**
Process a control-C break message.
Currently a place holder, remove the ASSERT when it gets implemented.
@param ErrNo Error infomration from the F reply packet or other source
**/
VOID
GdbCtrlCBreakMessage (
IN UINTN ErrNo
)
{
// See D.10.5 of gdb.pdf
// This should look like a break message. Should look like SIGINT
/* TODO: Make sure if we should do anything with ErrNo */
//Turn on the global Ctrl-C flag.
gCtrlCBreakFlag = TRUE;
}
/**
Parse the F reply packet and extract the return value and an ErrNo if it exists.
@param Packet Packet to parse like an F reply packet
@param ErrNo Buffer to hold Count bytes that were read
@retval -1 Error, not a valid F reply packet
@retval other Return the return code from the F reply packet
**/
INTN
GdbParseFReplyPacket (
IN CHAR8 *Packet,
OUT UINTN *ErrNo
)
{
INTN RetCode;
if (Packet[0] != 'F') {
// A valid responce would be an F packet
return -1;
}
RetCode = AsciiStrHexToUintn (&Packet[1]);
// Find 1st comma
for (;*Packet != '\0' && *Packet != ','; Packet++);
if (*Packet == '\0') {
*ErrNo = 0;
return RetCode;
}
*ErrNo = AsciiStrHexToUintn (++Packet);
// Find 2nd comma
for (;*Packet != '\0' && *Packet != ','; Packet++);
if (*Packet == '\0') {
return RetCode;
}
if (*(++Packet) == 'C') {
GdbCtrlCBreakMessage (*ErrNo);
}
return RetCode;
}
/**
Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates
the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero.
@param FileDescriptor Device to talk to.
@param Buffer Buffer to hold Count bytes that were read
@param Count Number of bytes to transfer.
@retval -1 Error
@retval {other} Number of bytes read.
**/
INTN
GdbRead (
IN INTN FileDescriptor,
OUT VOID *Buffer,
IN UINTN Count
)
{
CHAR8 Packet[128];
UINTN Size;
INTN RetCode;
UINTN ErrNo;
BOOLEAN ReceiveDone = FALSE;
// Send:
// "Fread,XX,YYYYYYYY,XX
//
// XX - FileDescriptor in ASCII
// YYYYYYYY - Buffer address in ASCII
// XX - Count in ASCII
// SS - check sum
//
Size = AsciiSPrint (Packet, sizeof (Packet), "Fread,%x,%x,%x", FileDescriptor, Buffer, Count);
// Packet array is too small if you got this ASSERT
ASSERT (Size < sizeof (Packet));
gProcessingFPacket = TRUE;
SendPacket (Packet);
Print ((CHAR16 *)L"Packet sent..\n");
do {
// Reply:
ReceivePacket (Packet, sizeof (Packet));
Print ((CHAR16 *)L"Command received..%c\n", Packet[0]);
// Process GDB commands
switch (Packet[0]) {
//Write memory command.
//M addr,length:XX...
case 'M':
WriteToMemory (Packet);
break;
//Fretcode, errno, Ctrl-C flag
//retcode - Count read
case 'F':
//Once target receives F reply packet that means the previous
//transactions are finished.
ReceiveDone = TRUE;
break;
//Send empty buffer
default :
SendNotSupported();
break;
}
} while (ReceiveDone == FALSE);
RetCode = GdbParseFReplyPacket (Packet, &ErrNo);
Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo);
if (ErrNo > 0) {
//Send error to the host if there is any.
SendError ((UINT8)ErrNo);
}
gProcessingFPacket = FALSE;
return RetCode;
}
/**
Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates
nothing was written. On error -1 is returned.
@param FileDescriptor Device to talk to.
@param Buffer Buffer to hold Count bytes that are to be written
@param Count Number of bytes to transfer.
@retval -1 Error
@retval {other} Number of bytes written.
**/
INTN
GdbWrite (
IN INTN FileDescriptor,
OUT CONST VOID *Buffer,
IN UINTN Count
)
{
CHAR8 Packet[128];
UINTN Size;
INTN RetCode;
UINTN ErrNo;
BOOLEAN ReceiveDone = FALSE;
// Send:
// #Fwrite,XX,YYYYYYYY,XX$SS
//
// XX - FileDescriptor in ASCII
// YYYYYYYY - Buffer address in ASCII
// XX - Count in ASCII
// SS - check sum
//
Size = AsciiSPrint (Packet, sizeof (Packet), "Fwrite,%x,%x,%x", FileDescriptor, Buffer, Count);
// Packet array is too small if you got this ASSERT
ASSERT (Size < sizeof (Packet));
SendPacket (Packet);
Print ((CHAR16 *)L"Packet sent..\n");
do {
// Reply:
ReceivePacket (Packet, sizeof (Packet));
Print ((CHAR16 *)L"Command received..%c\n", Packet[0]);
// Process GDB commands
switch (Packet[0]) {
//Read memory command.
//m addr,length.
case 'm':
ReadFromMemory (Packet);
break;
//Fretcode, errno, Ctrl-C flag
//retcode - Count read
case 'F':
//Once target receives F reply packet that means the previous
//transactions are finished.
ReceiveDone = TRUE;
break;
//Send empty buffer
default :
SendNotSupported();
break;
}
} while (ReceiveDone == FALSE);
RetCode = GdbParseFReplyPacket (Packet, &ErrNo);
Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo);
//Send error to the host if there is any.
if (ErrNo > 0) {
SendError((UINT8)ErrNo);
}
return RetCode;
}
/**
Reset the serial device.
@param This Protocol instance pointer.
@retval EFI_SUCCESS The device was reset.
@retval EFI_DEVICE_ERROR The serial device could not be reset.
**/
EFI_STATUS
EFIAPI
GdbSerialReset (
IN EFI_SERIAL_IO_PROTOCOL *This
)
{
return EFI_SUCCESS;
}
/**
Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
data buts, and stop bits on a serial device.
@param This Protocol instance pointer.
@param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
device's default interface speed.
@param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the
serial interface. A ReceiveFifoDepth value of 0 will use
the device's dfault FIFO depth.
@param Timeout The requested time out for a single character in microseconds.
This timeout applies to both the transmit and receive side of the
interface. A Timeout value of 0 will use the device's default time
out value.
@param Parity The type of parity to use on this serial device. A Parity value of
DefaultParity will use the device's default parity value.
@param DataBits The number of data bits to use on the serial device. A DataBits
vaule of 0 will use the device's default data bit setting.
@param StopBits The number of stop bits to use on this serial device. A StopBits
value of DefaultStopBits will use the device's default number of
stop bits.
@retval EFI_SUCCESS The device was reset.
@retval EFI_DEVICE_ERROR The serial device could not be reset.
**/
EFI_STATUS
EFIAPI
GdbSerialSetAttributes (
IN EFI_SERIAL_IO_PROTOCOL *This,
IN UINT64 BaudRate,
IN UINT32 ReceiveFifoDepth,
IN UINT32 Timeout,
IN EFI_PARITY_TYPE Parity,
IN UINT8 DataBits,
IN EFI_STOP_BITS_TYPE StopBits
)
{
return EFI_UNSUPPORTED;
}
/**
Set the control bits on a serial device
@param This Protocol instance pointer.
@param Control Set the bits of Control that are settable.
@retval EFI_SUCCESS The new control bits were set on the serial device.
@retval EFI_UNSUPPORTED The serial device does not support this operation.
@retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
**/
EFI_STATUS
EFIAPI
GdbSerialSetControl (
IN EFI_SERIAL_IO_PROTOCOL *This,
IN UINT32 Control
)
{
return EFI_UNSUPPORTED;
}
/**
Retrieves the status of thecontrol bits on a serial device
@param This Protocol instance pointer.
@param Control A pointer to return the current Control signals from the serial device.
@retval EFI_SUCCESS The control bits were read from the serial device.
@retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
**/
EFI_STATUS
EFIAPI
GdbSerialGetControl (
IN EFI_SERIAL_IO_PROTOCOL *This,
OUT UINT32 *Control
)
{
return EFI_UNSUPPORTED;
}
/**
Writes data to a serial device.
@param This Protocol instance pointer.
@param BufferSize On input, the size of the Buffer. On output, the amount of
data actually written.
@param Buffer The buffer of data to write
@retval EFI_SUCCESS The data was written.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_TIMEOUT The data write was stopped due to a timeout.
**/
EFI_STATUS
EFIAPI
GdbSerialWrite (
IN EFI_SERIAL_IO_PROTOCOL *This,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
)
{
GDB_SERIAL_DEV *SerialDev;
UINTN Return;
SerialDev = GDB_SERIAL_DEV_FROM_THIS (This);
Return = GdbWrite (SerialDev->OutFileDescriptor, Buffer, *BufferSize);
if (Return == (UINTN)-1) {
return EFI_DEVICE_ERROR;
}
if (Return != *BufferSize) {
*BufferSize = Return;
}
return EFI_SUCCESS;
}
/**
Writes data to a serial device.
@param This Protocol instance pointer.
@param BufferSize On input, the size of the Buffer. On output, the amount of
data returned in Buffer.
@param Buffer The buffer to return the data into.
@retval EFI_SUCCESS The data was read.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_TIMEOUT The data write was stopped due to a timeout.
**/
EFI_STATUS
EFIAPI
GdbSerialRead (
IN EFI_SERIAL_IO_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
GDB_SERIAL_DEV *SerialDev;
UINTN Return;
SerialDev = GDB_SERIAL_DEV_FROM_THIS (This);
Return = GdbRead (SerialDev->InFileDescriptor, Buffer, *BufferSize);
if (Return == (UINTN)-1) {
return EFI_DEVICE_ERROR;
}
if (Return != *BufferSize) {
*BufferSize = Return;
}
return EFI_SUCCESS;
}
//
// Template used to initailize the GDB Serial IO protocols
//
GDB_SERIAL_DEV gdbSerialDevTemplate = {
GDB_SERIAL_DEV_SIGNATURE,
NULL,
{ // SerialIo
SERIAL_IO_INTERFACE_REVISION,
GdbSerialReset,
GdbSerialSetAttributes,
GdbSerialSetControl,
GdbSerialGetControl,
GdbSerialWrite,
GdbSerialRead,
NULL
},
{ // SerialMode
0, // ControlMask
0, // Timeout
0, // BaudRate
1, // RceiveFifoDepth
0, // DataBits
0, // Parity
0 // StopBits
},
{
{
HARDWARE_DEVICE_PATH,
HW_VENDOR_DP,
{
(UINT8) (sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)),
(UINT8) ((sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)) >> 8)
},
EFI_SERIAL_IO_PROTOCOL_GUID,
},
0,
{
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
{
(UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)),
(UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL) >> 8)
}
},
},
GDB_STDIN,
GDB_STDOUT
};
/**
Make two serial consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB.
These console show up on the remote system running GDB
**/
VOID
GdbInitializeSerialConsole (
VOID
)
{
EFI_STATUS Status;
GDB_SERIAL_DEV *StdOutSerialDev;
GDB_SERIAL_DEV *StdErrSerialDev;
// Use the template to make a copy of the Serial Console private data structure.
StdOutSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV), &gdbSerialDevTemplate);
ASSERT (StdOutSerialDev != NULL);
// Fixup pointer after the copy
StdOutSerialDev->SerialIo.Mode = &StdOutSerialDev->SerialMode;
StdErrSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV), &gdbSerialDevTemplate);
ASSERT (StdErrSerialDev != NULL);
// Fixup pointer and modify stuff that is different for StdError
StdErrSerialDev->SerialIo.Mode = &StdErrSerialDev->SerialMode;
StdErrSerialDev->DevicePath.Index = 1;
StdErrSerialDev->OutFileDescriptor = GDB_STDERR;
// Make a new handle with Serial IO protocol and its device path on it.
Status = gBS->InstallMultipleProtocolInterfaces (
&StdOutSerialDev->Handle,
&gEfiSerialIoProtocolGuid, &StdOutSerialDev->SerialIo,
&gEfiDevicePathProtocolGuid, &StdOutSerialDev->DevicePath,
NULL
);
ASSERT_EFI_ERROR (Status);
// Make a new handle with Serial IO protocol and its device path on it.
Status = gBS->InstallMultipleProtocolInterfaces (
&StdErrSerialDev->Handle,
&gEfiSerialIoProtocolGuid, &StdErrSerialDev->SerialIo,
&gEfiDevicePathProtocolGuid, &StdErrSerialDev->DevicePath,
NULL
);
ASSERT_EFI_ERROR (Status);
}

View File

@@ -0,0 +1,963 @@
/** @file
Processor specific parts of the GDB stub
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 <GdbStubInternal.h>
//
// Array of exception types that need to be hooked by the debugger
//
EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
{ EXCEPT_X64_DIVIDE_ERROR, GDB_SIGFPE },
{ EXCEPT_X64_DEBUG, GDB_SIGTRAP },
{ EXCEPT_X64_NMI, GDB_SIGEMT },
{ EXCEPT_X64_BREAKPOINT, GDB_SIGTRAP },
{ EXCEPT_X64_OVERFLOW, GDB_SIGSEGV },
{ EXCEPT_X64_BOUND, GDB_SIGSEGV },
{ EXCEPT_X64_INVALID_OPCODE, GDB_SIGILL },
{ EXCEPT_X64_DOUBLE_FAULT, GDB_SIGEMT },
{ EXCEPT_X64_STACK_FAULT, GDB_SIGSEGV },
{ EXCEPT_X64_GP_FAULT, GDB_SIGSEGV },
{ EXCEPT_X64_PAGE_FAULT, GDB_SIGSEGV },
{ EXCEPT_X64_FP_ERROR, GDB_SIGEMT },
{ EXCEPT_X64_ALIGNMENT_CHECK, GDB_SIGEMT },
{ EXCEPT_X64_MACHINE_CHECK, GDB_SIGEMT }
};
// The offsets of registers SystemContextX64.
// The fields in the array are in the gdb ordering.
// HAVE TO DOUBLE-CHECK THE ORDER of the 24 regs
//
UINTN gRegisterOffsets[] = {
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rax),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rcx),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdx),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbx),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsp),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbp),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsi),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdi),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rip),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rflags),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Cs),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ss),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ds),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Es),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Fs),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Gs),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R8),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R9),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R10),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R11),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R12),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R13),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R14),
OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R15)
};
/**
Return the number of entries in the gExceptionType[]
@retval UINTN, the number of entries in the gExceptionType[] array.
**/
UINTN
MaxEfiException (
VOID
)
{
return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
}
/**
Return the number of entries in the gRegisters[]
@retval UINTN, the number of entries (registers) in the gRegisters[] array.
**/
UINTN
MaxRegisterCount (
VOID
)
{
return sizeof (gRegisterOffsets)/sizeof (UINTN);
}
/**
Check to see if the ISA is supported.
ISA = Instruction Set Architecture
@retval TRUE if Isa is supported
**/
BOOLEAN
CheckIsa (
IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
)
{
return (BOOLEAN)(Isa == IsaX64);
}
/**
This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
It is, by default, set to find the register pointer of the X64 member
@param SystemContext Register content at time of the exception
@param RegNumber The register to which we want to find a pointer
@retval the pointer to the RegNumber-th pointer
**/
UINTN *
FindPointerToRegister(
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber
)
{
UINT8 *TempPtr;
TempPtr = ((UINT8 *)SystemContext.SystemContextX64) + gRegisterOffsets[RegNumber];
return (UINTN *)TempPtr;
}
/**
Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
@param SystemContext Register content at time of the exception
@param RegNumber the number of the register that we want to read
@param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
@retval the pointer to the next character of the output buffer that is available to be written on.
**/
CHAR8 *
BasicReadRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber,
IN CHAR8 *OutBufPtr
)
{
UINTN RegSize;
RegSize = 0;
while (RegSize < 64) {
*OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
*OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];
RegSize = RegSize + 8;
}
return OutBufPtr;
}
/** p n
Reads the n-th register's value into an output buffer and sends it as a packet
@param SystemContext Register content at time of the exception
@param InBuffer Pointer to the input buffer received from gdb server
**/
VOID
ReadNthRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
)
{
UINTN RegNumber;
CHAR8 OutBuffer[17]; // 1 reg=16 hex chars, and the end '\0' (escape seq)
CHAR8 *OutBufPtr; // pointer to the output buffer
RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {
SendError (GDB_EINVALIDREGNUM);
return;
}
OutBufPtr = OutBuffer;
OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr);
*OutBufPtr = '\0'; // the end of the buffer
SendPacket (OutBuffer);
}
/** g
Reads the general registers into an output buffer and sends it as a packet
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
ReadGeneralRegisters (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
UINTN i;
CHAR8 OutBuffer[385]; // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
CHAR8 *OutBufPtr; // pointer to the output buffer
OutBufPtr = OutBuffer;
for(i = 0 ; i < MaxRegisterCount() ; i++) { // there are only 24 registers to read
OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr);
}
*OutBufPtr = '\0'; // the end of the buffer
SendPacket (OutBuffer);
}
/**
Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
@param SystemContext Register content at time of the exception
@param RegNumber the number of the register that we want to write
@param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
@retval the pointer to the next character of the input buffer that can be used
**/
CHAR8 *
BasicWriteRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN RegNumber,
IN CHAR8 *InBufPtr
)
{
UINTN RegSize;
UINTN TempValue; // the value transferred from a hex char
UINT64 NewValue; // the new value of the RegNumber-th Register
NewValue = 0;
RegSize = 0;
while (RegSize < 64) {
TempValue = HexCharToInt(*InBufPtr++);
if (TempValue < 0) {
SendError (GDB_EBADMEMDATA);
return NULL;
}
NewValue += (TempValue << (RegSize+4));
TempValue = HexCharToInt(*InBufPtr++);
if (TempValue < 0) {
SendError (GDB_EBADMEMDATA);
return NULL;
}
NewValue += (TempValue << RegSize);
RegSize = RegSize + 8;
}
*(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;
return InBufPtr;
}
/** P n...=r...
Writes the new value of n-th register received into the input buffer to the n-th register
@param SystemContext Register content at time of the exception
@param InBuffer Ponter to the input buffer received from gdb server
**/
VOID
EFIAPI
WriteNthRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
)
{
UINTN RegNumber;
CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
CHAR8 *RegNumBufPtr;
CHAR8 *InBufPtr; // pointer to the input buffer
// find the register number to write
InBufPtr = &InBuffer[1];
RegNumBufPtr = RegNumBuffer;
while (*InBufPtr != '=') {
*RegNumBufPtr++ = *InBufPtr++;
}
*RegNumBufPtr = '\0';
RegNumber = AsciiStrHexToUintn (RegNumBuffer);
// check if this is a valid Register Number
if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {
SendError (GDB_EINVALIDREGNUM);
return;
}
InBufPtr++; // skips the '=' character
BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
SendSuccess();
}
/** G XX...
Writes the new values received into the input buffer to the general registers
@param SystemContext Register content at time of the exception
@param InBuffer Pointer to the input buffer received from gdb server
**/
VOID
EFIAPI
WriteGeneralRegisters (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *InBuffer
)
{
UINTN i;
CHAR8 *InBufPtr; /// pointer to the input buffer
// check to see if the buffer is the right size which is
// 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 385
if (AsciiStrLen(InBuffer) != 385) { // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
//Bad message. Message is not the right length
SendError (GDB_EBADBUFSIZE);
return;
}
InBufPtr = &InBuffer[1];
// Read the new values for the registers from the input buffer to an array, NewValueArray.
// The values in the array are in the gdb ordering
for(i=0; i < MaxRegisterCount(); i++) { // there are only 16 registers to write
InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr);
}
SendSuccess();
}
/**
Insert Single Step in the SystemContext
@param SystemContext Register content at time of the exception
**/
VOID
AddSingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
SystemContext.SystemContextX64->Rflags |= TF_BIT; //Setting the TF bit.
}
/**
Remove Single Step in the SystemContext
@param SystemContext Register content at time of the exception
**/
VOID
RemoveSingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
SystemContext.SystemContextX64->Rflags &= ~TF_BIT; // clearing the TF bit.
}
/** c [addr ]
Continue. addr is Address to resume. If addr is omitted, resume at current
Address.
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
ContinueAtAddress (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
if (PacketData[1] != '\0') {
SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn(&PacketData[1]);
}
}
/** s [addr ]
Single step. addr is the Address at which to resume. If addr is omitted, resume
at same Address.
@param SystemContext Register content at time of the exception
**/
VOID
EFIAPI
SingleStep (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
if (PacketData[1] != '\0') {
SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn (&PacketData[1]);
}
AddSingleStep (SystemContext);
}
/**
Returns breakpoint data address from DR0-DR3 based on the input breakpoint
number
@param SystemContext Register content at time of the exception
@param BreakpointNumber Breakpoint number
@retval Address Data address from DR0-DR3 based on the
breakpoint number.
**/
UINTN
GetBreakpointDataAddress (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN BreakpointNumber
)
{
UINTN Address;
if (BreakpointNumber == 1) {
Address = SystemContext.SystemContextIa32->Dr0;
} else if (BreakpointNumber == 2) {
Address = SystemContext.SystemContextIa32->Dr1;
} else if (BreakpointNumber == 3) {
Address = SystemContext.SystemContextIa32->Dr2;
} else if (BreakpointNumber == 4) {
Address = SystemContext.SystemContextIa32->Dr3;
} else {
Address = 0;
}
return Address;
}
/**
Returns currently detected breakpoint value based on the register
DR6 B0-B3 field.
If no breakpoint is detected then it returns 0.
@param SystemContext Register content at time of the exception
@retval {1-4} Currently detected breakpoint value
@retval 0 No breakpoint detected.
**/
UINTN
GetBreakpointDetected (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
IA32_DR6 Dr6;
UINTN BreakpointNumber;
Dr6.UintN = SystemContext.SystemContextIa32->Dr6;
if (Dr6.Bits.B0 == 1) {
BreakpointNumber = 1;
} else if (Dr6.Bits.B1 == 1) {
BreakpointNumber = 2;
} else if (Dr6.Bits.B2 == 1) {
BreakpointNumber = 3;
} else if (Dr6.Bits.B3 == 1) {
BreakpointNumber = 4;
} else {
BreakpointNumber = 0; //No breakpoint detected
}
return BreakpointNumber;
}
/**
Returns Breakpoint type (InstructionExecution, DataWrite, DataRead
or DataReadWrite) based on the Breakpoint number
@param SystemContext Register content at time of the exception
@param BreakpointNumber Breakpoint number
@retval BREAK_TYPE Breakpoint type value read from register DR7 RWn
field. For unknown value, it returns NotSupported.
**/
BREAK_TYPE
GetBreakpointType (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN BreakpointNumber
)
{
IA32_DR7 Dr7;
BREAK_TYPE Type = NotSupported; //Default is NotSupported type
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if (BreakpointNumber == 1) {
Type = (BREAK_TYPE) Dr7.Bits.RW0;
} else if (BreakpointNumber == 2) {
Type = (BREAK_TYPE) Dr7.Bits.RW1;
} else if (BreakpointNumber == 3) {
Type = (BREAK_TYPE) Dr7.Bits.RW2;
} else if (BreakpointNumber == 4) {
Type = (BREAK_TYPE) Dr7.Bits.RW3;
}
return Type;
}
/**
Parses Length and returns the length which DR7 LENn field accepts.
For example: If we receive 1-Byte length then we should return 0.
Zero gets written to DR7 LENn field.
@param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
@retval Length Appropriate converted values which DR7 LENn field accepts.
**/
UINTN
ConvertLengthData (
IN UINTN Length
)
{
if (Length == 1) { //1-Byte length
return 0;
} else if (Length == 2) { //2-Byte length
return 1;
} else if (Length == 4) { //4-Byte length
return 3;
} else { //Undefined or 8-byte length
return 2;
}
}
/**
Finds the next free debug register. If all the registers are occupied then
EFI_OUT_OF_RESOURCES is returned.
@param SystemContext Register content at time of the exception
@param Register Register value (0 - 3 for the first free debug register)
@retval EFI_STATUS Appropriate status value.
**/
EFI_STATUS
FindNextFreeDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
OUT UINTN *Register
)
{
IA32_DR7 Dr7;
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if (Dr7.Bits.G0 == 0) {
*Register = 0;
} else if (Dr7.Bits.G1 == 0) {
*Register = 1;
} else if (Dr7.Bits.G2 == 0) {
*Register = 2;
} else if (Dr7.Bits.G3 == 0) {
*Register = 3;
} else {
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS;
}
/**
Enables the debug register. Writes Address value to appropriate DR0-3 register.
Sets LENn, Gn, RWn bits in DR7 register.
@param SystemContext Register content at time of the exception
@param Register Register value (0 - 3)
@param Address Breakpoint address value
@param Type Breakpoint type (Instruction, Data write,
Data read or write etc.)
@retval EFI_STATUS Appropriate status value.
**/
EFI_STATUS
EnableDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN Register,
IN UINTN Address,
IN UINTN Length,
IN UINTN Type
)
{
IA32_DR7 Dr7;
//Convert length data
Length = ConvertLengthData (Length);
//For Instruction execution, length should be 0
//(Ref. Intel reference manual 18.2.4)
if ((Type == 0) && (Length != 0)) {
return EFI_INVALID_PARAMETER;
}
//Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
//software breakpoint. We should send empty packet in both these cases.
if ((Type == (BREAK_TYPE)DataRead) ||
(Type == (BREAK_TYPE)SoftwareBreakpoint)) {
return EFI_UNSUPPORTED;
}
//Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if (Register == 0) {
SystemContext.SystemContextIa32->Dr0 = Address;
Dr7.Bits.G0 = 1;
Dr7.Bits.RW0 = Type;
Dr7.Bits.LEN0 = Length;
} else if (Register == 1) {
SystemContext.SystemContextIa32->Dr1 = Address;
Dr7.Bits.G1 = 1;
Dr7.Bits.RW1 = Type;
Dr7.Bits.LEN1 = Length;
} else if (Register == 2) {
SystemContext.SystemContextIa32->Dr2 = Address;
Dr7.Bits.G2 = 1;
Dr7.Bits.RW2 = Type;
Dr7.Bits.LEN2 = Length;
} else if (Register == 3) {
SystemContext.SystemContextIa32->Dr3 = Address;
Dr7.Bits.G3 = 1;
Dr7.Bits.RW3 = Type;
Dr7.Bits.LEN3 = Length;
} else {
return EFI_INVALID_PARAMETER;
}
//Update Dr7 with appropriate Gn, RWn and LENn bits
SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
return EFI_SUCCESS;
}
/**
Returns register number 0 - 3 for the maching debug register.
This function compares incoming Address, Type, Length and
if there is a match then it returns the appropriate register number.
In case of mismatch, function returns EFI_NOT_FOUND message.
@param SystemContext Register content at time of the exception
@param Address Breakpoint address value
@param Length Breakpoint length value
@param Type Breakpoint type (Instruction, Data write, Data read
or write etc.)
@param Register Register value to be returned
@retval EFI_STATUS Appropriate status value.
**/
EFI_STATUS
FindMatchingDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN Address,
IN UINTN Length,
IN UINTN Type,
OUT UINTN *Register
)
{
IA32_DR7 Dr7;
//Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
//software breakpoint. We should send empty packet in both these cases.
if ((Type == (BREAK_TYPE)DataRead) ||
(Type == (BREAK_TYPE)SoftwareBreakpoint)) {
return EFI_UNSUPPORTED;
}
//Convert length data
Length = ConvertLengthData(Length);
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if ((Dr7.Bits.G0 == 1) &&
(Dr7.Bits.LEN0 == Length) &&
(Dr7.Bits.RW0 == Type) &&
(Address == SystemContext.SystemContextIa32->Dr0)) {
*Register = 0;
} else if ((Dr7.Bits.G1 == 1) &&
(Dr7.Bits.LEN1 == Length) &&
(Dr7.Bits.RW1 == Type) &&
(Address == SystemContext.SystemContextIa32->Dr1)) {
*Register = 1;
} else if ((Dr7.Bits.G2 == 1) &&
(Dr7.Bits.LEN2 == Length) &&
(Dr7.Bits.RW2 == Type) &&
(Address == SystemContext.SystemContextIa32->Dr2)) {
*Register = 2;
} else if ((Dr7.Bits.G3 == 1) &&
(Dr7.Bits.LEN3 == Length) &&
(Dr7.Bits.RW3 == Type) &&
(Address == SystemContext.SystemContextIa32->Dr3)) {
*Register = 3;
} else {
Print ((CHAR16 *)L"No match found..\n");
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
/**
Disables the particular debug register.
@param SystemContext Register content at time of the exception
@param Register Register to be disabled
@retval EFI_STATUS Appropriate status value.
**/
EFI_STATUS
DisableDebugRegister (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN UINTN Register
)
{
IA32_DR7 Dr7;
UINTN Address = 0;
//Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
if (Register == 0) {
SystemContext.SystemContextIa32->Dr0 = Address;
Dr7.Bits.G0 = 0;
Dr7.Bits.RW0 = 0;
Dr7.Bits.LEN0 = 0;
} else if (Register == 1) {
SystemContext.SystemContextIa32->Dr1 = Address;
Dr7.Bits.G1 = 0;
Dr7.Bits.RW1 = 0;
Dr7.Bits.LEN1 = 0;
} else if (Register == 2) {
SystemContext.SystemContextIa32->Dr2 = Address;
Dr7.Bits.G2 = 0;
Dr7.Bits.RW2 = 0;
Dr7.Bits.LEN2 = 0;
} else if (Register == 3) {
SystemContext.SystemContextIa32->Dr3 = Address;
Dr7.Bits.G3 = 0;
Dr7.Bits.RW3 = 0;
Dr7.Bits.LEN3 = 0;
} else {
return EFI_INVALID_PARAMETER;
}
//Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
return EFI_SUCCESS;
}
/**
Z1, [addr], [length]
Z2, [addr], [length]
Z3, [addr], [length]
Z4, [addr], [length]
Insert hardware breakpoint/watchpoint at address addr of size length
@param SystemContext Register content at time of the exception
@param *PacketData Pointer to the Payload data for the packet
**/
VOID
EFIAPI
InsertBreakPoint (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
UINTN Type;
UINTN Address;
UINTN Length;
UINTN Register;
EFI_STATUS Status;
BREAK_TYPE BreakType = NotSupported;
UINTN ErrorCode;
ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
if (ErrorCode > 0) {
SendError ((UINT8)ErrorCode);
return;
}
switch (Type) {
case 0: //Software breakpoint
BreakType = SoftwareBreakpoint;
break;
case 1: //Hardware breakpoint
BreakType = InstructionExecution;
break;
case 2: //Write watchpoint
BreakType = DataWrite;
break;
case 3: //Read watchpoint
BreakType = DataRead;
break;
case 4: //Access watchpoint
BreakType = DataReadWrite;
break;
default :
Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type);
SendError (GDB_EINVALIDBRKPOINTTYPE);
return;
}
// Find next free debug register
Status = FindNextFreeDebugRegister (SystemContext, &Register);
if (EFI_ERROR(Status)) {
Print ((CHAR16 *)L"No space left on device\n");
SendError (GDB_ENOSPACE);
return;
}
// Write Address, length data at particular DR register
Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType);
if (EFI_ERROR(Status)) {
if (Status == EFI_UNSUPPORTED) {
Print ((CHAR16 *)L"Not supported\n");
SendNotSupported();
return;
}
Print ((CHAR16 *)L"Invalid argument\n");
SendError (GDB_EINVALIDARG);
return;
}
SendSuccess ();
}
/**
z1, [addr], [length]
z2, [addr], [length]
z3, [addr], [length]
z4, [addr], [length]
Remove hardware breakpoint/watchpoint at address addr of size length
@param *PacketData Pointer to the Payload data for the packet
**/
VOID
EFIAPI
RemoveBreakPoint (
IN EFI_SYSTEM_CONTEXT SystemContext,
IN CHAR8 *PacketData
)
{
UINTN Type;
UINTN Address;
UINTN Length;
UINTN Register;
BREAK_TYPE BreakType = NotSupported;
EFI_STATUS Status;
UINTN ErrorCode;
//Parse breakpoint packet data
ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
if (ErrorCode > 0) {
SendError ((UINT8)ErrorCode);
return;
}
switch (Type) {
case 0: //Software breakpoint
BreakType = SoftwareBreakpoint;
break;
case 1: //Hardware breakpoint
BreakType = InstructionExecution;
break;
case 2: //Write watchpoint
BreakType = DataWrite;
break;
case 3: //Read watchpoint
BreakType = DataRead;
break;
case 4: //Access watchpoint
BreakType = DataReadWrite;
break;
default :
SendError (GDB_EINVALIDBRKPOINTTYPE);
return;
}
//Find matching debug register
Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register);
if (EFI_ERROR(Status)) {
if (Status == EFI_UNSUPPORTED) {
Print ((CHAR16 *)L"Not supported.\n");
SendNotSupported();
return;
}
Print ((CHAR16 *)L"No matching register found.\n");
SendError (GDB_ENOSPACE);
return;
}
//Remove breakpoint
Status = DisableDebugRegister(SystemContext, Register);
if (EFI_ERROR(Status)) {
Print ((CHAR16 *)L"Invalid argument.\n");
SendError (GDB_EINVALIDARG);
return;
}
SendSuccess ();
}
VOID
InitializeProcessor (
VOID
)
{
}
BOOLEAN
ValidateAddress (
IN VOID *Address
)
{
return TRUE;
}
BOOLEAN
ValidateException (
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext
)
{
return TRUE;
}

View File

@@ -0,0 +1,122 @@
/** @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_ADD_EXTERNAL_COMMAND_LIB_H__
#define __EBL_ADD_EXTERNAL_COMMAND_LIB_H__
#include <PiDxe.h>
#include <Protocol/EblAddCommand.h>
EFI_STATUS
EFIAPI
EblAddExternalCommands (
IN const EBL_COMMAND_TABLE *EntryArray,
IN UINTN ArrayCount
);
/**
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
EFIAPI
EblGetCharKey (
IN OUT EFI_INPUT_KEY *Key,
IN UINTN TimeoutInSec,
IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL
);
/**
This routine is used prevent command output data from scrolling off the end
of the screen. The global gPageBreak is used to turn on or off this feature.
If the CurrentRow is near the end of the screen pause and print out a prompt
If the use hits Q to quit return TRUE else for any other key return FALSE.
PrefixNewline is used to figure out if a newline is needed before the prompt
string. This depends on the last print done before calling this function.
CurrentRow is updated by one on a call or set back to zero if a prompt is
needed.
@param CurrentRow Used to figure out if its the end of the page and updated
@param PrefixNewline Did previous print issue a newline
@return TRUE if Q was hit to quit, FALSE in all other cases.
**/
BOOLEAN
EFIAPI
EblAnyKeyToContinueQtoQuit (
IN UINTN *CurrentRow,
IN BOOLEAN PrefixNewline
);
#endif

View File

@@ -0,0 +1,48 @@
/** @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_LIB_H__
#define __EBL_LIB_H__
#include <PiDxe.h>
#include <Protocol/EblAddCommand.h>
VOID
EblAddCommand (
IN const EBL_COMMAND_TABLE *Entry
);
VOID
EblAddCommands (
IN const EBL_COMMAND_TABLE *EntryArray,
IN UINTN ArrayCount
);
//
// LIbrary constructor called directly from Ebl Code.
// This module calls EblAddCommand () or EblAddCommands () to register new commands
//
VOID
EblInitializeExternalCmd (
VOID
);
#endif

View File

@@ -0,0 +1,68 @@
/** @file
Abstractions for Ebl network accesses.
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_NETWORK_LIB_H__
#define __EBL_NETWORK_LIB_H__
#include <Protocol/PxeBaseCode.h>
EFI_STATUS
EFIAPI
EblGetCurrentIpAddress (
IN OUT EFI_IP_ADDRESS *Ip
);
EFI_STATUS
EFIAPI
EblGetCurrentMacAddress (
IN OUT EFI_MAC_ADDRESS *Mac
);
CHAR8 *
EFIAPI
EblLoadFileBootTypeString (
IN EFI_HANDLE Handle
);
EFI_STATUS
EFIAPI
EblPerformDHCP (
IN BOOLEAN SortOffers
);
EFI_STATUS
EFIAPI
EblSetStationIp (
IN EFI_IP_ADDRESS *NewStationIp, OPTIONAL
IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL
);
EFI_STATUS
EFIAPI
EblMtftp (
IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation,
IN OUT VOID *BufferPtr OPTIONAL,
IN BOOLEAN Overwrite,
IN OUT UINT64 *BufferSize,
IN UINTN *BlockSize OPTIONAL,
IN EFI_IP_ADDRESS *ServerIp,
IN UINT8 *Filename OPTIONAL,
IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL,
IN BOOLEAN DontUseBuffer
);
#endif

View File

@@ -0,0 +1,315 @@
/** @file
Library functions that perform file IO. Memory buffer, file system, and
fimrware volume operations are supproted.
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.
Basic support for opening files on different device types. The device string
is in the form of DevType:Path. Current DevType is required as there is no
current mounted device concept of current working directory concept implement
by this library.
Device names are case insensative and only check the leading characters for
unique matches. Thus the following are all the same:
LoadFile0:
l0:
L0:
Lo0:
Supported Device Names:
A0x1234:0x12 - A memory buffer starting at address 0x1234 for 0x12 bytes
l1: - EFI LoadFile device one.
B0: - EFI BlockIo zero.
fs3: - EFI Simple File System device 3
Fv2: - EFI Firmware VOlume device 2
1.2.3.4:name - TFTP IP and file name
**/
#ifndef __EFI_FILE_LIB_H__
#define __EFI_FILE_LIB_H__
#include <PiDxe.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/FirmwareVolumeBlock.h>
#include <Protocol/BlockIo.h>
#include <Protocol/LoadFile.h>
#include <Protocol/LoadFile.h>
#include <Protocol/SimpleFileSystem.h>
#include <Guid/FileInfo.h>
#include <Guid/FileSystemInfo.h>
#define MAX_PATHNAME 0x200
/// Type of the file that has been opened
typedef enum {
EfiOpenLoadFile,
EfiOpenMemoryBuffer,
EfiOpenFirmwareVolume,
EfiOpenFileSystem,
EfiOpenBlockIo,
EfiOpenTftp,
EfiOpenMaxValue
} EFI_OPEN_FILE_TYPE;
/// Public information about the open file
typedef struct {
UINTN Version; // Common information
EFI_OPEN_FILE_TYPE Type;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_STATUS LastError;
EFI_HANDLE EfiHandle;
CHAR8 *DeviceName;
CHAR8 *FileName;
UINT64 CurrentPosition; // Information for Seek
UINT64 MaxPosition;
UINTN BaseOffset; // Base offset for hexdump command
UINTN Size; // Valid for all types other than l#:
UINT8 *Buffer; // Information valid for A#:
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; // Information valid for Fv#:
EFI_GUID FvNameGuid;
EFI_SECTION_TYPE FvSectionType;
EFI_FV_FILETYPE FvType;
EFI_FV_FILE_ATTRIBUTES FvAttributes;
EFI_PHYSICAL_ADDRESS FvStart;
UINTN FvSize;
EFI_FILE *FsFileHandle; // Information valid for Fs#:
EFI_FILE_SYSTEM_INFO *FsInfo;
EFI_FILE_INFO *FsFileInfo;
EFI_BLOCK_IO_MEDIA FsBlockIoMedia; // Information valid for Fs#: or B#:
UINTN DiskOffset; // Information valid for B#:
EFI_LOAD_FILE_PROTOCOL *LoadFile; // Information valid for l#:
EFI_IP_ADDRESS ServerIp; // Information valid for t:
BOOLEAN IsDirty;
BOOLEAN IsBufferValid;
} EFI_OPEN_FILE;
/// Type of Seek to perform
typedef enum {
EfiSeekStart,
EfiSeekCurrent,
EfiSeekEnd,
EfiSeekMax
} EFI_SEEK_TYPE;
/**
Open a device named by PathName. The PathName includes a device name and
path seperated by a :. See file header for more details on the PathName
syntax. There is no checking to prevent a file from being opened more than
one type.
SectionType is only used to open an FV. Each file in an FV contains multiple
secitons and only the SectionType section is opened.
For any file that is opened with EfiOpen() must be closed with EfiClose().
@param PathName Path to parse to open
@param OpenMode Same as EFI_FILE.Open()
@param SectionType Section in FV to open.
@return NULL Open failed
@return Valid EFI_OPEN_FILE handle
**/
EFI_OPEN_FILE *
EfiOpen (
IN CHAR8 *PathName,
IN CONST UINT64 OpenMode,
IN CONST EFI_SECTION_TYPE SectionType
);
EFI_STATUS
EfiCopyFile (
IN CHAR8 *DestinationFile,
IN CHAR8 *SourceFile
);
/**
Use DeviceType and Index to form a valid PathName and try and open it.
@param DeviceType Device type to open
@param Index Device Index to use. Zero relative.
@return NULL Open failed
@return Valid EFI_OPEN_FILE handle
**/
EFI_OPEN_FILE *
EfiDeviceOpenByType (
IN EFI_OPEN_FILE_TYPE DeviceType,
IN UINTN Index
);
/**
Close a file handle opened by EfiOpen() and free all resources allocated by
EfiOpen().
@param Stream Open File Handle
@return EFI_INVALID_PARAMETER Stream is not an Open File
@return EFI_SUCCESS Steam closed
**/
EFI_STATUS
EfiClose (
IN EFI_OPEN_FILE *Stream
);
/**
Return the size of the file represented by Stream. Also return the current
Seek position. Opening a file will enable a valid file size to be returned.
LoadFile is an exception as a load file size is set to zero.
@param Stream Open File Handle
@return 0 Stream is not an Open File or a valid LoadFile handle
**/
UINTN
EfiTell (
IN EFI_OPEN_FILE *Stream,
OUT UINT64 *CurrentPosition OPTIONAL
);
/**
Seek to the Offset locaiton in the file. LoadFile and FV device types do
not support EfiSeek(). It is not possible to grow the file size using
EfiSeek().
SeekType defines how use Offset to calculate the new file position:
EfiSeekStart : Position = Offset
EfiSeekCurrent: Position is Offset bytes from the current position
EfiSeekEnd : Only supported if Offset is zero to seek to end of file.
@param Stream Open File Handle
@param Offset Offset to seek too.
@param SeekType Type of seek to perform
@return EFI_INVALID_PARAMETER Stream is not an Open File
@return EFI_UNSUPPORTED LoadFile and FV doe not support Seek
@return EFI_NOT_FOUND Seek past the end of the file.
@return EFI_SUCCESS Steam closed
**/
EFI_STATUS
EfiSeek (
IN EFI_OPEN_FILE *Stream,
IN EFI_LBA Offset,
IN EFI_SEEK_TYPE SeekType
);
/**
Read BufferSize bytes from the current locaiton in the file. For load file
and FV case you must read the entire file.
@param Stream Open File Handle
@param Buffer Caller allocated buffer.
@param BufferSize Size of buffer in bytes.
@return EFI_SUCCESS Stream is not an Open File
@return EFI_END_OF_FILE Tried to read past the end of the file
@return EFI_INVALID_PARAMETER Stream is not an open file handle
@return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read
@return "other" Error returned from device read
**/
EFI_STATUS
EfiRead (
IN EFI_OPEN_FILE *Stream,
OUT VOID *Buffer,
OUT UINTN *BufferSize
);
/**
Read the entire file into a buffer. This routine allocates the buffer and
returns it to the user full of the read data.
This is very useful for load flie where it's hard to know how big the buffer
must be.
@param Stream Open File Handle
@param Buffer Pointer to buffer to return.
@param BufferSize Pointer to Size of buffer return..
@return EFI_SUCCESS Stream is not an Open File
@return EFI_END_OF_FILE Tried to read past the end of the file
@return EFI_INVALID_PARAMETER Stream is not an open file handle
@return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read
@return "other" Error returned from device read
**/
EFI_STATUS
EfiReadAllocatePool (
IN EFI_OPEN_FILE *Stream,
OUT VOID **Buffer,
OUT UINTN *BufferSize
);
/**
Write data back to the file.
@param Stream Open File Handle
@param Buffer Pointer to buffer to return.
@param BufferSize Pointer to Size of buffer return..
@return EFI_SUCCESS Stream is not an Open File
@return EFI_END_OF_FILE Tried to read past the end of the file
@return EFI_INVALID_PARAMETER Stream is not an open file handle
@return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read
@return "other" Error returned from device write
**/
EFI_STATUS
EfiWrite (
IN EFI_OPEN_FILE *Stream,
OUT VOID *Buffer,
OUT UINTN *BufferSize
);
/**
Return the number of devices of the current type active in the system
@param Type Device type to check
@return 0 Invalid type
**/
UINTN
EfiGetDeviceCounts (
IN EFI_OPEN_FILE_TYPE Type
);
#endif

View File

@@ -0,0 +1,58 @@
/** @file
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 __EFI_RESET_SYSTEM_LIB_H___
#define __EFI_RESET_SYSTEM_LIB_H___
/**
Resets the entire platform.
@param ResetType The type of reset to perform.
@param ResetStatus The status code for the reset.
@param DataSize The size, in bytes, of WatchdogData.
@param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
EfiResetShutdown the data buffer starts with a Null-terminated
Unicode string, optionally followed by additional binary data.
**/
EFI_STATUS
EFIAPI
LibResetSystem (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN CHAR16 *ResetData OPTIONAL
);
/**
Initialize any infrastructure required for LibResetSystem () to function.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
**/
EFI_STATUS
EFIAPI
LibInitializeResetSystem (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
#endif

View File

@@ -0,0 +1,107 @@
/** @file
Basic serial IO abstaction for GDB
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 __GDB_SERIAL_LIB_H__
#define __GDB_SERIAL_LIB_H__
/**
Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
data buts, and stop bits on a serial device. This call is optional as the serial
port will be set up with defaults base on PCD values.
@param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
device's default interface speed.
@param Parity The type of parity to use on this serial device. A Parity value of
DefaultParity will use the device's default parity value.
@param DataBits The number of data bits to use on the serial device. A DataBits
vaule of 0 will use the device's default data bit setting.
@param StopBits The number of stop bits to use on this serial device. A StopBits
value of DefaultStopBits will use the device's default number of
stop bits.
@retval EFI_SUCCESS The device was configured.
@retval EFI_DEVICE_ERROR The serial device could not be coonfigured.
**/
RETURN_STATUS
EFIAPI
GdbSerialInit (
IN UINT64 BaudRate,
IN UINT8 Parity,
IN UINT8 DataBits,
IN UINT8 StopBits
);
/**
Check to see if a character is available from GDB. Do not read the character as that is
done via GdbGetChar().
@return TRUE - Character availible
@return FALSE - Character not availible
**/
BOOLEAN
EFIAPI
GdbIsCharAvailable (
VOID
);
/**
Get a character from GDB. This function must be able to run in interrupt context.
@return A character from GDB
**/
CHAR8
EFIAPI
GdbGetChar (
VOID
);
/**
Send a character to GDB. This function must be able to run in interrupt context.
@param Char Send a character to GDB
**/
VOID
EFIAPI
GdbPutChar (
IN CHAR8 Char
);
/**
Send an ASCII string to GDB. This function must be able to run in interrupt context.
@param String Send a string to GDB
**/
VOID
GdbPutString (
IN CHAR8 *String
);
#endif

View File

@@ -0,0 +1,165 @@
/** @file
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 __RUNTIME_SERVICES_LIB_H__
#define __RUNTIME_SERVICES_LIB_H__
VOID
LibMtcInitialize (VOID);
VOID
LibMtcVirtualAddressChangeEvent (VOID);
EFI_STATUS
EFIAPI
LibMtcGetNextHighMonotonicCount (
OUT UINT32 *HighCount
);
EFI_STATUS
LibMtcGetNextMonotonicCount (
OUT UINT64 *Count
);
VOID
LibVariableInitialize (VOID);
VOID
LibVariableVirtualAddressChangeEvent (VOID);
EFI_STATUS
LibGetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes OPTIONAL,
IN OUT UINTN *DataSize,
OUT VOID *Data
);
EFI_STATUS
LibGetNextVariableName (
IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
);
EFI_STATUS
LibSetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
);
EFI_STATUS
LibQueryVariableInfo (
IN UINT32 Attributes,
OUT UINT64 *MaximumVariableStorageSize,
OUT UINT64 *RemainingVariableStorageSize,
OUT UINT64 *MaximumVariableSize
);
VOID
LibResetInitializeReset (VOID);
VOID
LibResetVirtualAddressChangeEvent (VOID);
VOID
LibResetSystem (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN CHAR16 *ResetData OPTIONAL
);
VOID
LibCapsuleInitialize (VOID);
VOID
LibCapsuleVirtualAddressChangeEvent (VOID);
EFI_STATUS
LibUpdateCapsule (
IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray,
IN UINTN CapsuleCount,
IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
);
EFI_STATUS
QueryCapsuleCapabilities (
IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray,
IN UINTN CapsuleCount,
OUT UINT64 *MaxiumCapsuleSize,
OUT EFI_RESET_TYPE *ResetType
);
VOID
LibRtcInitialize (VOID);
VOID
LibRtcVirtualAddressChangeEvent (VOID);
EFI_STATUS
LibGetTime (
OUT EFI_TIME *Time,
OUT EFI_TIME_CAPABILITIES *Capabilities
);
EFI_STATUS
LibSetTime (
IN EFI_TIME *Time
);
EFI_STATUS
LibGetWakeupTime (
OUT BOOLEAN *Enabled,
OUT BOOLEAN *Pending,
OUT EFI_TIME *Time
);
EFI_STATUS
LibSetWakeupTime (
IN BOOLEAN Enabled,
OUT EFI_TIME *Time
);
VOID
LibReportStatusCodeInitialize (VOID);
VOID
LibReportStatusCodeVirtualAddressChangeEvent (VOID);
EFI_STATUS
LibReportStatusCode (
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
IN EFI_GUID *CallerId,
IN EFI_STATUS_CODE_DATA *Data OPTIONAL
);
#endif

View File

@@ -0,0 +1,766 @@
/** @file
Library that helps implement monolithic PEI. (SEC goes to DXE)
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 __PRE_PI_LIB_H__
#define __PRE_PI_LIB_H__
/**
This service enables discovery of additional firmware volumes.
@param Instance This instance of the firmware volume to find. The value 0 is the
Boot Firmware Volume (BFV).
@param FwVolHeader Pointer to the firmware volume header of the volume to return.
@retval EFI_SUCCESS The volume was found.
@retval EFI_NOT_FOUND The volume was not found.
@retval EFI_INVALID_PARAMETER FwVolHeader is NULL.
**/
EFI_STATUS
EFIAPI
FfsFindNextVolume (
IN UINTN Instance,
IN OUT EFI_PEI_FV_HANDLE *VolumeHandle
);
/**
This service enables discovery of additional firmware files.
@param SearchType A filter to find files only of this type.
@param FwVolHeader Pointer to the firmware volume header of the volume to search.
This parameter must point to a valid FFS volume.
@param FileHeader Pointer to the current file from which to begin searching.
@retval EFI_SUCCESS The file was found.
@retval EFI_NOT_FOUND The file was not found.
@retval EFI_NOT_FOUND The header checksum was not zero.
**/
EFI_STATUS
EFIAPI
FfsFindNextFile (
IN EFI_FV_FILETYPE SearchType,
IN EFI_PEI_FV_HANDLE VolumeHandle,
IN OUT EFI_PEI_FILE_HANDLE *FileHandle
);
/**
This service enables discovery sections of a given type within a valid FFS file.
@param SearchType The value of the section type to find.
@param FfsFileHeader A pointer to the file header that contains the set of sections to
be searched.
@param SectionData A pointer to the discovered section, if successful.
@retval EFI_SUCCESS The section was found.
@retval EFI_NOT_FOUND The section was not found.
**/
EFI_STATUS
EFIAPI
FfsFindSectionData (
IN EFI_SECTION_TYPE SectionType,
IN EFI_PEI_FILE_HANDLE FileHandle,
OUT VOID **SectionData
);
/**
Find a file in the volume by name
@param FileName A pointer to the name of the file to
find within the firmware volume.
@param VolumeHandle The firmware volume to search FileHandle
Upon exit, points to the found file's
handle or NULL if it could not be found.
@retval EFI_SUCCESS File was found.
@retval EFI_NOT_FOUND File was not found.
@retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or
FileName was NULL.
**/
EFI_STATUS
EFIAPI
FfsFindByName (
IN CONST EFI_GUID *FileName,
IN CONST EFI_PEI_FV_HANDLE VolumeHandle,
OUT EFI_PEI_FILE_HANDLE *FileHandle
);
/**
Get information about the file by name.
@param FileHandle Handle of the file.
@param FileInfo Upon exit, points to the file's
information.
@retval EFI_SUCCESS File information returned.
@retval EFI_INVALID_PARAMETER If FileHandle does not
represent a valid file.
@retval EFI_INVALID_PARAMETER If FileInfo is NULL.
**/
EFI_STATUS
EFIAPI
FfsGetFileInfo (
IN CONST EFI_PEI_FILE_HANDLE FileHandle,
OUT EFI_FV_FILE_INFO *FileInfo
);
/**
Get Information about the volume by name
@param VolumeHandle Handle of the volume.
@param VolumeInfo Upon exit, points to the volume's
information.
@retval EFI_SUCCESS File information returned.
@retval EFI_INVALID_PARAMETER If FileHandle does not
represent a valid file.
@retval EFI_INVALID_PARAMETER If FileInfo is NULL.
**/
EFI_STATUS
EFIAPI
FfsGetVolumeInfo (
IN EFI_PEI_FV_HANDLE VolumeHandle,
OUT EFI_FV_INFO *VolumeInfo
);
/**
Get Fv image from the FV type file, then add FV & FV2 Hob.
@param FileHandle File handle of a Fv type file.
@retval EFI_NOT_FOUND FV image can't be found.
@retval EFI_SUCCESS Successfully to process it.
**/
EFI_STATUS
EFIAPI
FfsProcessFvFile (
IN EFI_PEI_FILE_HANDLE FvFileHandle
);
/**
Search through every FV until you find a file of type FileType
@param FileType File handle of a Fv type file.
@param Volumehandle On succes Volume Handle of the match
@param FileHandle On success File Handle of the match
@retval EFI_NOT_FOUND FV image can't be found.
@retval EFI_SUCCESS Successfully found FileType
**/
EFI_STATUS
EFIAPI
FfsAnyFvFindFirstFile (
IN EFI_FV_FILETYPE FileType,
OUT EFI_PEI_FV_HANDLE *VolumeHandle,
OUT EFI_PEI_FILE_HANDLE *FileHandle
);
/**
Get Fv image from the FV type file, then add FV & FV2 Hob.
@param FileHandle File handle of a Fv type file.
@retval EFI_NOT_FOUND FV image can't be found.
@retval EFI_SUCCESS Successfully to process it.
**/
EFI_STATUS
EFIAPI
FfsProcessFvFile (
IN EFI_PEI_FILE_HANDLE FvFileHandle
);
/**
This service enables PEIMs to ascertain the present value of the boot mode.
@retval BootMode
**/
EFI_BOOT_MODE
EFIAPI
GetBootMode (
VOID
);
/**
This service enables PEIMs to update the boot mode variable.
@param BootMode The value of the boot mode to set.
@retval EFI_SUCCESS The value was successfully updated
**/
EFI_STATUS
EFIAPI
SetBootMode (
IN EFI_BOOT_MODE BootMode
);
/**
This service enables a PEIM to ascertain the address of the list of HOBs in memory.
@param HobList A pointer to the list of HOBs that the PEI Foundation will initialize.
@retval EFI_SUCCESS The list was successfully returned.
@retval EFI_NOT_AVAILABLE_YET The HOB list is not yet published.
**/
VOID *
EFIAPI
GetHobList (
VOID
);
/**
Updates the pointer to the HOB list.
@param HobList Hob list pointer to store
**/
EFI_STATUS
EFIAPI
SetHobList (
IN VOID *HobList
);
/**
Retrieves the magic value from the PE/COFF header.
@param Hdr The buffer in which to return the PE32, PE32+, or TE header.
@return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32
@return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+
**/
VOID
CreateHobList (
IN VOID *MemoryBegin,
IN UINTN MemoryLength,
IN VOID *HobBase,
IN VOID *StackBase
);
/**
This service enables PEIMs to create various types of HOBs.
@param Type The type of HOB to be installed.
@param Length The length of the HOB to be added.
@retval !NULL The HOB was successfully created.
@retval NULL There is no additional space for HOB creation.
**/
VOID *
CreateHob (
IN UINT16 HobType,
IN UINT16 HobLenght
);
/**
Returns the next instance of a HOB type from the starting HOB.
This function searches the first instance of a HOB type from the starting HOB pointer.
If there does not exist such HOB type from the starting HOB pointer, it will return NULL.
In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
unconditionally: it returns HobStart back if HobStart itself meets the requirement;
caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
If HobStart is NULL, then ASSERT().
@param Type The HOB type to return.
@param HobStart The starting HOB pointer to search from.
@return The next instance of a HOB type from the starting HOB.
**/
VOID *
EFIAPI
GetNextHob (
IN UINT16 Type,
IN CONST VOID *HobStart
);
/**
Returns the first instance of a HOB type among the whole HOB list.
This function searches the first instance of a HOB type among the whole HOB list.
If there does not exist such HOB type in the HOB list, it will return NULL.
@param Type The HOB type to return.
@return The next instance of a HOB type from the starting HOB.
**/
VOID *
EFIAPI
GetFirstHob (
IN UINT16 Type
);
/**
This function searches the first instance of a HOB from the starting HOB pointer.
Such HOB should satisfy two conditions:
its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
If there does not exist such HOB from the starting HOB pointer, it will return NULL.
Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
to extract the data section and its size info respectively.
In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
unconditionally: it returns HobStart back if HobStart itself meets the requirement;
caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
If Guid is NULL, then ASSERT().
If HobStart is NULL, then ASSERT().
@param Guid The GUID to match with in the HOB list.
@param HobStart A pointer to a Guid.
@return The next instance of the matched GUID HOB from the starting HOB.
**/
VOID *
EFIAPI
GetNextGuidHob (
IN CONST EFI_GUID *Guid,
IN CONST VOID *HobStart
);
/**
This function searches the first instance of a HOB among the whole HOB list.
Such HOB should satisfy two conditions:
its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
If there does not exist such HOB from the starting HOB pointer, it will return NULL.
Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
to extract the data section and its size info respectively.
If Guid is NULL, then ASSERT().
@param Guid The GUID to match with in the HOB list.
@return The first instance of the matched GUID HOB among the whole HOB list.
**/
VOID *
EFIAPI
GetFirstGuidHob (
IN CONST EFI_GUID *Guid
);
/**
Builds a HOB for a loaded PE32 module.
This function builds a HOB for a loaded PE32 module.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If ModuleName is NULL, then ASSERT().
If there is no additional space for HOB creation, then ASSERT().
@param ModuleName The GUID File Name of the module.
@param MemoryAllocationModule The 64 bit physical address of the module.
@param ModuleLength The length of the module in bytes.
@param EntryPoint The 64 bit physical address of the module entry point.
**/
VOID
EFIAPI
BuildModuleHob (
IN CONST EFI_GUID *ModuleName,
IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule,
IN UINT64 ModuleLength,
IN EFI_PHYSICAL_ADDRESS EntryPoint
);
/**
Builds a HOB that describes a chunk of system memory.
This function builds a HOB that describes a chunk of system memory.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param ResourceType The type of resource described by this HOB.
@param ResourceAttribute The resource attributes of the memory described by this HOB.
@param PhysicalStart The 64 bit physical address of memory described by this HOB.
@param NumberOfBytes The length of the memory described by this HOB in bytes.
**/
VOID
EFIAPI
BuildResourceDescriptorHob (
IN EFI_RESOURCE_TYPE ResourceType,
IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
IN EFI_PHYSICAL_ADDRESS PhysicalStart,
IN UINT64 NumberOfBytes
);
/**
Builds a GUID HOB with a certain data length.
This function builds a customized HOB tagged with a GUID for identification
and returns the start address of GUID HOB data so that caller can fill the customized data.
The HOB Header and Name field is already stripped.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If Guid is NULL, then ASSERT().
If there is no additional space for HOB creation, then ASSERT().
If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
@param Guid The GUID to tag the customized HOB.
@param DataLength The size of the data payload for the GUID HOB.
@return The start address of GUID HOB data.
**/
VOID *
EFIAPI
BuildGuidHob (
IN CONST EFI_GUID *Guid,
IN UINTN DataLength
);
/**
Copies a data buffer to a newly-built HOB.
This function builds a customized HOB tagged with a GUID for identification,
copies the input data to the HOB data field and returns the start address of the GUID HOB data.
The HOB Header and Name field is already stripped.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If Guid is NULL, then ASSERT().
If Data is NULL and DataLength > 0, then ASSERT().
If there is no additional space for HOB creation, then ASSERT().
If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
@param Guid The GUID to tag the customized HOB.
@param Data The data to be copied into the data field of the GUID HOB.
@param DataLength The size of the data payload for the GUID HOB.
@return The start address of GUID HOB data.
**/
VOID *
EFIAPI
BuildGuidDataHob (
IN CONST EFI_GUID *Guid,
IN VOID *Data,
IN UINTN DataLength
);
/**
Builds a Firmware Volume HOB.
This function builds a Firmware Volume HOB.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The base address of the Firmware Volume.
@param Length The size of the Firmware Volume in bytes.
**/
VOID
EFIAPI
BuildFvHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
);
/**
Builds a Firmware Volume HOB and a resrouce descriptor hob
This function builds a Firmware Volume HOB.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The base address of the Firmware Volume.
@param Length The size of the Firmware Volume in bytes.
**/
VOID
EFIAPI
BuildFvHobs (
IN EFI_PHYSICAL_ADDRESS PhysicalStart,
IN UINT64 NumberOfBytes,
IN EFI_RESOURCE_ATTRIBUTE_TYPE *ResourceAttribute OPTIONAL
);
/**
Builds a EFI_HOB_TYPE_FV2 HOB.
This function builds a EFI_HOB_TYPE_FV2 HOB.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The base address of the Firmware Volume.
@param Length The size of the Firmware Volume in bytes.
@param FvName The name of the Firmware Volume.
@param FileName The name of the file.
**/
VOID
EFIAPI
BuildFv2Hob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN CONST EFI_GUID *FvName,
IN CONST EFI_GUID *FileName
);
/**
Builds a Capsule Volume HOB.
This function builds a Capsule Volume HOB.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The base address of the Capsule Volume.
@param Length The size of the Capsule Volume in bytes.
**/
VOID
EFIAPI
BuildCvHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
);
/**
Builds a HOB for the CPU.
This function builds a HOB for the CPU.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param SizeOfMemorySpace The maximum physical memory addressability of the processor.
@param SizeOfIoSpace The maximum physical I/O addressability of the processor.
**/
VOID
EFIAPI
BuildCpuHob (
IN UINT8 SizeOfMemorySpace,
IN UINT8 SizeOfIoSpace
);
/**
Builds a HOB for the Stack.
This function builds a HOB for the stack.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The 64 bit physical address of the Stack.
@param Length The length of the stack in bytes.
**/
VOID
EFIAPI
BuildStackHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
);
/**
Update the Stack Hob if the stack has been moved
@param BaseAddress The 64 bit physical address of the Stack.
@param Length The length of the stack in bytes.
**/
VOID
UpdateStackHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
);
/**
Builds a HOB for the BSP store.
This function builds a HOB for BSP store.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The 64 bit physical address of the BSP.
@param Length The length of the BSP store in bytes.
@param MemoryType Type of memory allocated by this HOB.
**/
VOID
EFIAPI
BuildBspStoreHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN EFI_MEMORY_TYPE MemoryType
);
/**
Builds a HOB for the memory allocation.
This function builds a HOB for the memory allocation.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The 64 bit physical address of the memory.
@param Length The length of the memory allocation in bytes.
@param MemoryType Type of memory allocated by this HOB.
**/
VOID
EFIAPI
BuildMemoryAllocationHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN EFI_MEMORY_TYPE MemoryType
);
/**
Allocates one or more 4KB pages of type EfiBootServicesData.
Allocates the number of 4KB pages of MemoryType and returns a pointer to the
allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
is returned. If there is not enough memory remaining to satisfy the request, then NULL is
returned.
@param Pages The number of 4 KB pages to allocate.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocatePages (
IN UINTN Pages
);
/**
Allocates a buffer of type EfiBootServicesData.
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
@param AllocationSize The number of bytes to allocate.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocatePool (
IN UINTN AllocationSize
);
/**
Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
returned. If there is not enough memory at the specified alignment remaining to satisfy the
request, then NULL is returned.
If Alignment is not a power of two and Alignment is not zero, then ASSERT().
@param Pages The number of 4 KB pages to allocate.
@param Alignment The requested alignment of the allocation. Must be a power of two.
If Alignment is zero, then byte alignment is used.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocateAlignedPages (
IN UINTN Pages,
IN UINTN Alignment
);
EFI_STATUS
EFIAPI
LoadPeCoffImage (
IN VOID *PeCoffImage,
OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
OUT UINT64 *ImageSize,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint
);
EFI_STATUS
EFIAPI
LoadDxeCoreFromFfsFile (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN UINTN StackSize
);
EFI_STATUS
EFIAPI
LoadDxeCoreFromFv (
IN UINTN *FvInstance, OPTIONAL
IN UINTN StackSize
);
EFI_STATUS
EFIAPI
DecompressFirstFv (
VOID
);
VOID
EFIAPI
AddDxeCoreReportStatusCodeCallback (
VOID
);
#endif

View File

@@ -0,0 +1,138 @@
/** @file
Implement EFI RealTimeClock runtime services via Lib.
Currently this driver does not support runtime virtual calling.
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 __REAL_TIME_CLOCK_LIB__
#define __REAL_TIME_CLOCK_LIB__
/**
Returns the current time and date information, and the time-keeping capabilities
of the hardware platform.
@param Time A pointer to storage to receive a snapshot of the current time.
@param Capabilities An optional pointer to a buffer to receive the real time clock
device's capabilities.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER Time is NULL.
@retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
**/
EFI_STATUS
EFIAPI
LibGetTime (
OUT EFI_TIME *Time,
OUT EFI_TIME_CAPABILITIES *Capabilities
);
/**
Sets the current local time and date information.
@param Time A pointer to the current time.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER A time field is out of range.
@retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
**/
EFI_STATUS
EFIAPI
LibSetTime (
IN EFI_TIME *Time
);
/**
Returns the current wakeup alarm clock setting.
@param Enabled Indicates if the alarm is currently enabled or disabled.
@param Pending Indicates if the alarm signal is pending and requires acknowledgement.
@param Time The current alarm setting.
@retval EFI_SUCCESS The alarm settings were returned.
@retval EFI_INVALID_PARAMETER Any parameter is NULL.
@retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
**/
EFI_STATUS
EFIAPI
LibGetWakeupTime (
OUT BOOLEAN *Enabled,
OUT BOOLEAN *Pending,
OUT EFI_TIME *Time
);
/**
Sets the system wakeup alarm clock time.
@param Enabled Enable or disable the wakeup alarm.
@param Time If Enable is TRUE, the time to set the wakeup alarm for.
@retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
Enable is FALSE, then the wakeup alarm was disabled.
@retval EFI_INVALID_PARAMETER A time field is out of range.
@retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
@retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
**/
EFI_STATUS
EFIAPI
LibSetWakeupTime (
IN BOOLEAN Enabled,
OUT EFI_TIME *Time
);
/**
This is the declaration of an EFI image entry point. This can be the entry point to an application
written to this specification, an EFI boot service driver, or an EFI runtime driver.
@param ImageHandle Handle that identifies the loaded image.
@param SystemTable System Table for this image.
@retval EFI_SUCCESS The operation completed successfully.
**/
EFI_STATUS
EFIAPI
LibRtcInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
/**
Fixup internal data so that EFI can be call in virtual mode.
Call the passed in Child Notify event and convert any pointers in
lib to virtual mode.
@param[in] Event The Event that is being processed
@param[in] Context Event Context
**/
VOID
EFIAPI
LibRtcVirtualNotifyEvent (
IN EFI_EVENT Event,
IN VOID *Context
);
#endif

View File

@@ -0,0 +1,42 @@
/** @file
Protocol is used to help implement DebugSupport.RegisterPeriodicCallback() functionality.
This enables the DXE timer driver to support the periodic callback function so the
DebugSupport driver does not need to contain platform specific information about how a timer
works.
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 __DEBUG_SUPPORT_PERIODIC_CALLBACK_H__
#define __DEBUG_SUPPORT_PERIODIC_CALLBACK_H__
#include <Protocol/DebugSupport.h>
typedef struct _EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL;
// {9546E07C-2CBB-4c88-986C-CD341086F044}
#define EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL_GUID \
{ 0x9546e07c, 0x2cbb, 0x4c88, { 0x98, 0x6c, 0xcd, 0x34, 0x10, 0x86, 0xf0, 0x44 } }
//
// DebugSupport protocol definition
//
struct _EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL {
EFI_PERIODIC_CALLBACK PeriodicCallback;
};
extern EFI_GUID gEfiDebugSupportPeriodicCallbackProtocolGuid;
#endif

View File

@@ -0,0 +1,156 @@
/** @file
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.
**/
/** @file
Abstraction for hardware based interrupt routine
Copyright (c) 2009 Apple Inc.
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_ADD_COMMAND_H__
#define __EBL_ADD_COMMAND_H__
//
// Protocol GUID
//
// AEDA2428-9A22-4637-9B21-545E28FBB829
#define EBL_ADD_COMMAND_PROTOCOL_GUID \
{ 0xaeda2428, 0x9a22, 0x4637, { 0x9b, 0x21, 0x54, 0x5e, 0x28, 0xfb, 0xb8, 0x29 } }
typedef struct _EBL_ADD_COMMAND_PROTOCOL EBL_ADD_COMMAND_PROTOCOL;
typedef
EFI_STATUS
(EFIAPI *EBL_COMMMAND) (
IN UINTN Argc,
IN CHAR8 **Argv
);
typedef struct {
CHAR8 *Name;
CHAR8 *HelpSummary;
CHAR8 *Help;
EBL_COMMMAND Command;
} EBL_COMMAND_TABLE;
/**
Add a single command table entry.
@param EntryArray Pointer EBL_COMMAND_TABLE of the command that is being added
**/
typedef
VOID
(EFIAPI *EBL_ADD_COMMAND) (
IN const EBL_COMMAND_TABLE *Entry
);
/**
Add a multiple command table entry.
@param EntryArray Pointer EBL_COMMAND_TABLE of the commands that are being added
@param ArrayCount Nuber of commands in the EntryArray.
**/
typedef
VOID
(EFIAPI *EBL_ADD_COMMANDS) (
IN const EBL_COMMAND_TABLE *EntryArray,
IN UINTN ArrayCount
);
typedef
VOID
(EFIAPI *EBL_GET_CHAR_CALL_BACK) (
IN UINTN ElapsedTime
);
/**
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
**/
typedef
EFI_STATUS
(EFIAPI *EBL_GET_CHAR_KEY) (
IN OUT EFI_INPUT_KEY *Key,
IN UINTN TimeoutInSec,
IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL
);
/**
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.
**/
typedef
BOOLEAN
(EFIAPI *EBL_ANY_KEY_CONTINUE_Q_QUIT) (
IN UINTN *CurrentRow,
IN BOOLEAN PrefixNewline
);
struct _EBL_ADD_COMMAND_PROTOCOL {
EBL_ADD_COMMAND AddCommand;
EBL_ADD_COMMANDS AddCommands;
// Commands to reuse EBL infrastructure
EBL_GET_CHAR_KEY EblGetCharKey;
EBL_ANY_KEY_CONTINUE_Q_QUIT EblAnyKeyToContinueQtoQuit;
};
extern EFI_GUID gEfiEblAddCommandProtocolGuid;
#endif

View File

@@ -0,0 +1,58 @@
/** @file
Deal with devices that just exist in memory space.
To follow the EFI driver model you need a root handle to start with. An
EFI driver will have a driver binding protocol (Supported, Start, Stop)
that is used to layer on top of a handle via a gBS->ConnectController.
The first handle has to just be in the system to make that work. For
PCI it is a PCI Root Bridge IO protocol that provides the root.
On an embedded system with MMIO device we need a handle to just
show up. That handle will have this protocol and a device path
protocol on it.
For an ethernet device the device path must contain a MAC address device path
node.
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 __EMBEDDED_DEVICE_PROTOCOL_H__
#define __EMBEDDED_DEVICE_PROTOCOL_H__
//
// Protocol GUID
//
// BF4B9D10-13EC-43dd-8880-E90B718F27DE
#define EMBEDDED_DEVICE_PROTOCOL_GUID \
{ 0xbf4b9d10, 0x13ec, 0x43dd, { 0x88, 0x80, 0xe9, 0xb, 0x71, 0x8f, 0x27, 0xde } }
typedef struct {
UINT16 VendorId;
UINT16 DeviceId;
UINT16 RevisionId;
UINT16 SubsystemId;
UINT16 SubsystemVendorId;
UINT8 ClassCode[3];
UINT8 HeaderSize;
UINTN BaseAddress;
} EMBEDDED_DEVICE_PROTOCOL;
extern EFI_GUID gEmbeddedDeviceGuid;
#endif

View File

@@ -0,0 +1,94 @@
/** @file
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 __EMBEDDED_EXTERNAL_DEVICE_H__
#define __EMBEDDED_EXTERNAL_DEVICE_H__
//
// Protocol GUID
//
#define EMBEDDED_EXTERNAL_DEVICE_PROTOCOL_GUID { 0x735F8C64, 0xD696, 0x44D0, { 0xBD, 0xF2, 0x44, 0x7F, 0xD0, 0x5A, 0x54, 0x06 }}
//
// Protocol interface structure
//
typedef struct _EMBEDDED_EXTERNAL_DEVICE EMBEDDED_EXTERNAL_DEVICE;
//
// Function Prototypes
//
typedef
EFI_STATUS
(EFIAPI *EMBEDDED_EXTERNAL_DEVICE_READ) (
IN EMBEDDED_EXTERNAL_DEVICE *This,
IN UINTN Register,
IN UINTN Length,
OUT VOID *Buffer
)
/*++
Routine Description:
Read a set of contiguous external device registers.
Arguments:
This - pointer to protocol
Offset - starting register number
Length - number of bytes to read
Buffer - destination buffer
Returns:
EFI_SUCCESS - registers read successfully
--*/
;
typedef
EFI_STATUS
(EFIAPI *EMBEDDED_EXTERNAL_DEVICE_WRITE) (
IN EMBEDDED_EXTERNAL_DEVICE *This,
IN UINTN Register,
IN UINTN Length,
IN VOID *Buffer
)
/*++
Routine Description:
Write to a set of contiguous external device registers.
Arguments:
This - pointer to protocol
Offset - starting register number
Length - number of bytes to write
Buffer - source buffer
Returns:
EFI_SUCCESS - registers written successfully
--*/
;
struct _EMBEDDED_EXTERNAL_DEVICE {
EMBEDDED_EXTERNAL_DEVICE_READ Read;
EMBEDDED_EXTERNAL_DEVICE_WRITE Write;
};
extern EFI_GUID gEmbeddedExternalDeviceProtocolGuid;
#endif // __EMBEDDED_EXTERNAL_DEVICE_H__

View File

@@ -0,0 +1,167 @@
/** @file
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 __EMBEDDED_GPIO_H__
#define __EMBEDDED_GPIO_H__
//
// Protocol interface structure
//
typedef struct _EMBEDDED_GPIO EMBEDDED_GPIO;
//
// Data Types
//
typedef UINTN EMBEDDED_GPIO_PIN;
#define GPIO(Port, Pin) ((EMBEDDED_GPIO_PIN)(((Port) << (16)) | (Pin)))
#define GPIO_PIN(x) ((EMBEDDED_GPIO_PIN)(x) & (0xFFFF))
#define GPIO_PORT(x) ((EMBEDDED_GPIO_PIN)(x) >> (16))
typedef enum {
GPIO_MODE_INPUT = 0x00,
GPIO_MODE_OUTPUT_0 = 0x0E,
GPIO_MODE_OUTPUT_1 = 0x0F,
GPIO_MODE_SPECIAL_FUNCTION_2 = 0x02,
GPIO_MODE_SPECIAL_FUNCTION_3 = 0x03,
GPIO_MODE_SPECIAL_FUNCTION_4 = 0x04,
GPIO_MODE_SPECIAL_FUNCTION_5 = 0x05,
GPIO_MODE_SPECIAL_FUNCTION_6 = 0x06,
GPIO_MODE_SPECIAL_FUNCTION_7 = 0x07
} EMBEDDED_GPIO_MODE;
typedef enum {
GPIO_PULL_NONE,
GPIO_PULL_UP,
GPIO_PULL_DOWN
} EMBEDDED_GPIO_PULL;
//
// Function Prototypes
//
typedef
EFI_STATUS
(EFIAPI *EMBEDDED_GPIO_GET) (
IN EMBEDDED_GPIO *This,
IN EMBEDDED_GPIO_PIN Gpio,
OUT UINTN *Value
);
/*++
Routine Description:
Gets the state of a GPIO pin
Arguments:
This - pointer to protocol
Gpio - which pin to read
Value - state of the pin
Returns:
EFI_SUCCESS - GPIO state returned in Value
--*/
typedef
EFI_STATUS
(EFIAPI *EMBEDDED_GPIO_SET) (
IN EMBEDDED_GPIO *This,
IN EMBEDDED_GPIO_PIN Gpio,
IN EMBEDDED_GPIO_MODE Mode
);
/*++
Routine Description:
Sets the state of a GPIO pin
Arguments:
This - pointer to protocol
Gpio - which pin to modify
Mode - mode to set
Returns:
EFI_SUCCESS - GPIO set as requested
--*/
typedef
EFI_STATUS
(EFIAPI *EMBEDDED_GPIO_GET_MODE) (
IN EMBEDDED_GPIO *This,
IN EMBEDDED_GPIO_PIN Gpio,
OUT EMBEDDED_GPIO_MODE *Mode
);
/*++
Routine Description:
Gets the mode (function) of a GPIO pin
Arguments:
This - pointer to protocol
Gpio - which pin
Mode - pointer to output mode value
Returns:
EFI_SUCCESS - mode value retrieved
--*/
typedef
EFI_STATUS
(EFIAPI *EMBEDDED_GPIO_SET_PULL) (
IN EMBEDDED_GPIO *This,
IN EMBEDDED_GPIO_PIN Gpio,
IN EMBEDDED_GPIO_PULL Direction
);
/*++
Routine Description:
Sets the pull-up / pull-down resistor of a GPIO pin
Arguments:
This - pointer to protocol
Gpio - which pin
Direction - pull-up, pull-down, or none
Returns:
EFI_SUCCESS - pin was set
--*/
struct _EMBEDDED_GPIO {
EMBEDDED_GPIO_GET Get;
EMBEDDED_GPIO_SET Set;
EMBEDDED_GPIO_GET_MODE GetMode;
EMBEDDED_GPIO_SET_PULL SetPull;
};
extern EFI_GUID gEmbeddedGpioProtocolGuid;
#endif

View File

@@ -0,0 +1,151 @@
/** @file
Abstraction for hardware based interrupt routine
On non IA-32 systems it is common to have a single hardware interrupt vector
and a 2nd layer of software that routes the interrupt handlers based on the
interrupt source. This protocol enables this routing. The driver implementing
this protocol is responsible for clearing the pending interrupt in the
interrupt routing hardware. The HARDWARE_INTERRUPT_HANDLER is responsible
for clearing interrupt sources from individual devices.
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 __HARDWARE_INTERRUPT_H__
#define __HARDWARE_INTERRUPT_H__
#include <Protocol/DebugSupport.h>
//
// Protocol GUID
//
// EAB39028-3D05-4316-AD0C-D64808DA3FF1
#define EFI_HARDWARE_INTERRUPT_PROTOCOL_GGUID \
{ 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } }
typedef struct _EFI_HARDWARE_INTERRUPT_PROTOCOL EFI_HARDWARE_INTERRUPT_PROTOCOL;
typedef UINTN HARDWARE_INTERRUPT_SOURCE;
/**
C Interrupt Handler calledin the interrupt context when Source interrupt is active.
@param Source Source of the interrupt. Hardware routing off a specific platform defines
what source means.
@param SystemContext Pointer to system register context. Mostly used by debuggers and will
update the system context after the return from the interrupt if
modified. Don't change these values unless you know what you are doing
**/
typedef
VOID
(EFIAPI *HARDWARE_INTERRUPT_HANDLER) (
IN HARDWARE_INTERRUPT_SOURCE Source,
IN EFI_SYSTEM_CONTEXT SystemContext
);
/**
Register Handler for the specified interrupt source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@param Handler Callback for interrupt. NULL to unregister
@retval EFI_SUCCESS Source was updated to support Handler.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
typedef
EFI_STATUS
(EFIAPI *HARDWARE_INTERRUPT_REGISTER) (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source,
IN HARDWARE_INTERRUPT_HANDLER Handler
);
/**
Enable interrupt source Source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@retval EFI_SUCCESS Source interrupt enabled.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
typedef
EFI_STATUS
(EFIAPI *HARDWARE_INTERRUPT_ENABLE) (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source
);
/**
Disable interrupt source Source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@retval EFI_SUCCESS Source interrupt disabled.
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
**/
typedef
EFI_STATUS
(EFIAPI *HARDWARE_INTERRUPT_DISABLE) (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source
);
/**
Return current state of interrupt source Source.
@param This Instance pointer for this protocol
@param Source Hardware source of the interrupt
@param InterruptState TRUE: source enabled, FALSE: source disabled.
@retval EFI_SUCCESS InterruptState is valid
@retval EFI_DEVICE_ERROR InterruptState is not valid
**/
typedef
EFI_STATUS
(EFIAPI *HARDWARE_INTERRUPT_INTERRUPT_STATE) (
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
IN HARDWARE_INTERRUPT_SOURCE Source,
IN BOOLEAN *InterruptState
);
struct _EFI_HARDWARE_INTERRUPT_PROTOCOL {
HARDWARE_INTERRUPT_REGISTER RegisterInterruptSource;
HARDWARE_INTERRUPT_ENABLE EnableInterruptSource;
HARDWARE_INTERRUPT_DISABLE DisableInterruptSource;
HARDWARE_INTERRUPT_INTERRUPT_STATE GetInterruptSourceState;
};
extern EFI_GUID gHardwareInterruptProtocolGuid;
#endif

View File

@@ -0,0 +1,156 @@
/** @file
Add external EblCmd Lib
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 <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/EblAddExternalCommandLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
STATIC BOOLEAN gInstalledCommand = FALSE;
STATIC EFI_EVENT mEblCommandRegistration = NULL;
STATIC const EBL_COMMAND_TABLE *mAddExternalCmdLibTemplate = NULL;
STATIC UINTN mAddExternalCmdLibTemplateSize = 0;
EBL_ADD_COMMAND_PROTOCOL *gEblExternalCommand = 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
EFIAPI
EblGetCharKey (
IN OUT EFI_INPUT_KEY *Key,
IN UINTN TimeoutInSec,
IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL
)
{
if (gEblExternalCommand != NULL) {
return gEblExternalCommand->EblGetCharKey (Key, TimeoutInSec, CallBack);
}
return EFI_TIMEOUT;
}
/**
This routine is used prevent command output data from scrolling off the end
of the screen. The global gPageBreak is used to turn on or off this feature.
If the CurrentRow is near the end of the screen pause and print out a prompt
If the use hits Q to quit return TRUE else for any other key return FALSE.
PrefixNewline is used to figure out if a newline is needed before the prompt
string. This depends on the last print done before calling this function.
CurrentRow is updated by one on a call or set back to zero if a prompt is
needed.
@param CurrentRow Used to figure out if its the end of the page and updated
@param PrefixNewline Did previous print issue a newline
@return TRUE if Q was hit to quit, FALSE in all other cases.
**/
BOOLEAN
EFIAPI
EblAnyKeyToContinueQtoQuit (
IN UINTN *CurrentRow,
IN BOOLEAN PrefixNewline
)
{
if (gEblExternalCommand != NULL) {
return gEblExternalCommand->EblAnyKeyToContinueQtoQuit (CurrentRow, PrefixNewline);
}
return FALSE;
}
/**
Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is
reinstalled.
@param Event The Event that is being processed
@param Context Event Context
**/
VOID
EFIAPI
EblAddCommandNotificationEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
if (!gInstalledCommand) {
Status = gBS->LocateProtocol (&gEfiEblAddCommandProtocolGuid, NULL, (VOID **)&gEblExternalCommand);
if (!EFI_ERROR (Status)) {
gEblExternalCommand->AddCommands (mAddExternalCmdLibTemplate, mAddExternalCmdLibTemplateSize);
gInstalledCommand = TRUE;
}
}
}
/**
The user Entry Point for the driver. The user code starts with this function
as the real entry point for the image goes into a library that calls this
function.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point is executed successfully.
@retval other Some error occurs when executing this entry point.
**/
EFI_STATUS
EFIAPI
EblAddExternalCommands (
IN const EBL_COMMAND_TABLE *EntryArray,
IN UINTN ArrayCount
)
{
if (mAddExternalCmdLibTemplate != NULL) {
return EFI_ALREADY_STARTED;
}
mAddExternalCmdLibTemplate = EntryArray;
mAddExternalCmdLibTemplateSize = ArrayCount;
EfiCreateProtocolNotifyEvent (
&gEfiEblAddCommandProtocolGuid,
TPL_CALLBACK,
EblAddCommandNotificationEvent,
NULL,
&mEblCommandRegistration
);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,47 @@
#%HEADER%
#/** @file
# Component description file for the entry point to a EFIDXE Drivers
#
# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification
# Copyright (c) 2007 - 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]
INF_VERSION = 0x00010005
BASE_NAME = EblAddExternalCommandLib
FILE_GUID = 9195D970-C6F7-484E-8013-5B03C89C3B81
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = EblAddExternalCommandLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
EblAddExternalCommandLib.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
UefiBootServicesTableLib
UefiLib
[Protocols]
[Guids]

View File

@@ -0,0 +1,28 @@
/** @file
Null EblCmdLib
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 <PiDxe.h>
#include <Library/EblCmdLib.h>
VOID
EblInitializeExternalCmd (
VOID
)
{
return;
}

View File

@@ -0,0 +1,45 @@
#%HEADER%
#/** @file
# Component description file for the entry point to a EFIDXE Drivers
#
# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification
# Copyright (c) 2007 - 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]
INF_VERSION = 0x00010005
BASE_NAME = EblCmdLibNull
FILE_GUID = 3513C4E2-06D6-4921-9C2B-E938777BA79E
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = EfiCmdLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
EblCmdLibNull.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
[Protocols]
[Guids]

View File

@@ -0,0 +1,173 @@
/** @file
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 <Uefi.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/SimpleNetwork.h>
#include <Protocol/PxeBaseCode.h>
BOOLEAN gUseIpv6 = FALSE;
EFI_STATUS
EFIAPI
EblGetCurrentIpAddress (
IN OUT EFI_IP_ADDRESS *Ip
)
{
EFI_STATUS Status;
EFI_PXE_BASE_CODE_PROTOCOL *Pxe;
Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);
if (EFI_ERROR(Status)) {
return Status;
}
Status = Pxe->Start (Pxe, gUseIpv6);
if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
return Status;
}
CopyMem (Ip, &Pxe->Mode->StationIp, sizeof (EFI_IP_ADDRESS));
return Status;
}
EFI_STATUS
EFIAPI
EblGetCurrentMacAddress (
IN OUT EFI_MAC_ADDRESS *Mac
)
{
EFI_STATUS Status;
EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNet;
Status = gBS->LocateProtocol (&gEfiSimpleNetworkProtocolGuid, NULL, (VOID **)&SimpleNet);
if (EFI_ERROR(Status)) {
return Status;
}
CopyMem (SimpleNet->Mode->CurrentAddress.Addr, Mac, sizeof (EFI_MAC_ADDRESS));
return Status;
}
CHAR8 *
EFIAPI
EblLoadFileBootTypeString (
IN EFI_HANDLE Handle
)
{
EFI_STATUS Status;
VOID *NullPtr;
Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, &NullPtr);
if (!EFI_ERROR (Status)) {
return "EFI PXE Network Boot";
}
return "";
}
EFI_STATUS
EFIAPI
EblPerformDHCP (
IN BOOLEAN SortOffers
)
{
EFI_STATUS Status;
EFI_PXE_BASE_CODE_PROTOCOL *Pxe;
Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);
if (EFI_ERROR(Status)) {
return Status;
}
Status = Pxe->Start (Pxe, gUseIpv6);
if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
return Status;
}
Status = Pxe->Dhcp(Pxe, TRUE);
return Status;
}
EFI_STATUS
EFIAPI
EblSetStationIp (
IN EFI_IP_ADDRESS *NewStationIp, OPTIONAL
IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL
)
{
EFI_STATUS Status;
EFI_PXE_BASE_CODE_PROTOCOL *Pxe;
Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);
if (EFI_ERROR(Status)) {
return Status;
}
Status = Pxe->Start (Pxe, gUseIpv6);
if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
return Status;
}
Status = Pxe->SetStationIp (Pxe, NewStationIp, NewSubnetMask);
return Status;
}
EFI_STATUS
EFIAPI
EblMtftp (
IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation,
IN OUT VOID *BufferPtr OPTIONAL,
IN BOOLEAN Overwrite,
IN OUT UINT64 *BufferSize,
IN UINTN *BlockSize OPTIONAL,
IN EFI_IP_ADDRESS *ServerIp,
IN UINT8 *Filename OPTIONAL,
IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL,
IN BOOLEAN DontUseBuffer
)
{
EFI_STATUS Status;
EFI_PXE_BASE_CODE_PROTOCOL *Pxe;
Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe);
if (EFI_ERROR(Status)) {
return Status;
}
Status = Pxe->Mtftp (
Pxe,
Operation,
BufferPtr,
Overwrite,
BufferSize,
BlockSize,
ServerIp,
Filename,
Info,
DontUseBuffer
);
return Status;
}

View File

@@ -0,0 +1,28 @@
#%HEADER%
#
# Copyright (c) 2005 - 2009 Apple Computer, Inc. All rights reserved.
#
#
#
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = EblNetworkLib
FILE_GUID = D885869A-7869-47DB-9429-DE03C318BCFD
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = EblNetworkLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
[sources.common]
EblNetworkLib.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[Protocols]
gEfiSimpleNetworkProtocolGuid
gEfiPxeBaseCodeProtocolGuid
[Depex]
TRUE

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
#%HEADER%
#/** @file
# Component description file for the entry point to a EFIDXE Drivers
#
# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification
# Copyright (c) 2007 - 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]
INF_VERSION = 0x00010005
BASE_NAME = EfiFileLib
FILE_GUID = d8c640db-73ba-48f5-a7ed-8e93c6012491
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = EfiFileLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
EfiFileLib.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
BaseLib
MemoryAllocationLib
DevicePathLib
PrintLib
BaseMemoryLib
UefiLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
DebugLib
EblNetworkLib
[Protocols]
gEfiBlockIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
gEfiDiskIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
gEfiSimpleFileSystemProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
gEfiLoadFileProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
[Guids]
gEfiFileInfoGuid
gEfiFileSystemInfoGuid

View File

@@ -0,0 +1,187 @@
/** @file
Basic serial IO abstaction for GDB
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 <Uefi.h>
#include <Library/GdbSerialLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/DebugPort.h>
EFI_DEBUGPORT_PROTOCOL *gDebugPort = NULL;
UINTN gTimeOut = 0;
/**
The constructor function initializes the UART.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
**/
RETURN_STATUS
EFIAPI
GdbSerialLibDebugPortConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **)&gDebugPort);
if (!EFI_ERROR (Status)) {
gTimeOut = PcdGet32 (PcdGdbMaxPacketRetryCount);
gDebugPort->Reset (gDebugPort);
}
return Status;
}
/**
Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
data buts, and stop bits on a serial device. This call is optional as the serial
port will be set up with defaults base on PCD values.
@param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
device's default interface speed.
@param Parity The type of parity to use on this serial device. A Parity value of
DefaultParity will use the device's default parity value.
@param DataBits The number of data bits to use on the serial device. A DataBits
vaule of 0 will use the device's default data bit setting.
@param StopBits The number of stop bits to use on this serial device. A StopBits
value of DefaultStopBits will use the device's default number of
stop bits.
@retval EFI_SUCCESS The device was configured.
@retval EFI_DEVICE_ERROR The serial device could not be coonfigured.
**/
RETURN_STATUS
EFIAPI
GdbSerialInit (
IN UINT64 BaudRate,
IN UINT8 Parity,
IN UINT8 DataBits,
IN UINT8 StopBits
)
{
EFI_STATUS Status;
Status = gDebugPort->Reset (gDebugPort);
return Status;
}
/**
Check to see if a character is available from GDB. Do not read the character as that is
done via GdbGetChar().
@return TRUE - Character availible
@return FALSE - Character not availible
**/
BOOLEAN
EFIAPI
GdbIsCharAvailable (
VOID
)
{
EFI_STATUS Status;
Status = gDebugPort->Poll (gDebugPort);
return (Status == EFI_SUCCESS ? TRUE : FALSE);
}
/**
Get a character from GDB. This function must be able to run in interrupt context.
@return A character from GDB
**/
CHAR8
EFIAPI
GdbGetChar (
VOID
)
{
EFI_STATUS Status;
CHAR8 Char;
UINTN BufferSize;
do {
BufferSize = sizeof (Char);
Status = gDebugPort->Read (gDebugPort, gTimeOut, &BufferSize, &Char);
} while (EFI_ERROR (Status) || BufferSize != sizeof (Char));
return Char;
}
/**
Send a character to GDB. This function must be able to run in interrupt context.
@param Char Send a character to GDB
**/
VOID
EFIAPI
GdbPutChar (
IN CHAR8 Char
)
{
EFI_STATUS Status;
UINTN BufferSize;
do {
BufferSize = sizeof (Char);
Status = gDebugPort->Write (gDebugPort, gTimeOut, &BufferSize, &Char);
} while (EFI_ERROR (Status) || BufferSize != sizeof (Char));
return;
}
/**
Send an ASCII string to GDB. This function must be able to run in interrupt context.
@param String Send a string to GDB
**/
VOID
GdbPutString (
IN CHAR8 *String
)
{
// We could performance enhance this function by calling gDebugPort->Write ()
while (*String != '\0') {
GdbPutChar (*String);
String++;
}
}

View File

@@ -0,0 +1,50 @@
#%HEADER%
#/** @file
# Component description file for Base PCI Cf8 Library.
#
# PCI CF8 Library that uses I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles.
# Layers on top of an I/O Library instance.
# 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]
INF_VERSION = 0x00010005
BASE_NAME = GdbSerialDebugPortLib
FILE_GUID = 42ABB10A-660A-4BEC-AEFA-CC94AB4D993D
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = GdbSerialLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
CONSTRUCTOR = GdbSerialLibDebugPortConstructor
[Sources.common]
GdbSerialDebugPortLib.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
DebugLib
IoLib
[Protocols.common]
gEfiDebugPortProtocolGuid
[FixedPcd.common]
gEmbeddedTokenSpaceGuid.PcdGdbBaudRate|115200
gEmbeddedTokenSpaceGuid.PcdGdbDataBits|8
gEmbeddedTokenSpaceGuid.PcdGdbParity|1
gEmbeddedTokenSpaceGuid.PcdGdbStopBits|1
gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount

View File

@@ -0,0 +1,262 @@
/** @file
Basic serial IO abstaction for GDB
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 <Uefi.h>
#include <Library/GdbSerialLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/DebugLib.h>
//---------------------------------------------
// UART Register Offsets
//---------------------------------------------
#define BAUD_LOW_OFFSET 0x00
#define BAUD_HIGH_OFFSET 0x01
#define IER_OFFSET 0x01
#define LCR_SHADOW_OFFSET 0x01
#define FCR_SHADOW_OFFSET 0x02
#define IR_CONTROL_OFFSET 0x02
#define FCR_OFFSET 0x02
#define EIR_OFFSET 0x02
#define BSR_OFFSET 0x03
#define LCR_OFFSET 0x03
#define MCR_OFFSET 0x04
#define LSR_OFFSET 0x05
#define MSR_OFFSET 0x06
//---------------------------------------------
// UART Register Bit Defines
//---------------------------------------------
#define LSR_TXRDY 0x20
#define LSR_RXDA 0x01
#define DLAB 0x01
#define ENABLE_FIFO 0x01
#define CLEAR_FIFOS 0x06
// IO Port Base for the UART
UINTN gPort;
/**
The constructor function initializes the UART.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
**/
RETURN_STATUS
EFIAPI
GdbSerialLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
UINT64 BaudRate;
UINT8 DataBits;
UINT8 Parity;
UINT8 StopBits;
gPort = (UINTN)PcdGet32 (PcdGdbUartPort);
BaudRate = PcdGet64 (PcdGdbBaudRate);
Parity = PcdGet8 (PcdGdbParity);
DataBits = PcdGet8 (PcdGdbDataBits);
StopBits = PcdGet8 (PcdGdbStopBits);
return GdbSerialInit (BaudRate, Parity, DataBits, StopBits);
}
/**
Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
data buts, and stop bits on a serial device. This call is optional as the serial
port will be set up with defaults base on PCD values.
@param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
device's default interface speed.
@param Parity The type of parity to use on this serial device. A Parity value of
DefaultParity will use the device's default parity value.
@param DataBits The number of data bits to use on the serial device. A DataBits
vaule of 0 will use the device's default data bit setting.
@param StopBits The number of stop bits to use on this serial device. A StopBits
value of DefaultStopBits will use the device's default number of
stop bits.
@retval EFI_SUCCESS The device was configured.
@retval EFI_DEVICE_ERROR The serial device could not be coonfigured.
**/
RETURN_STATUS
EFIAPI
GdbSerialInit (
IN UINT64 BaudRate,
IN UINT8 Parity,
IN UINT8 DataBits,
IN UINT8 StopBits
)
{
UINTN Divisor;
UINT8 OutputData;
UINT8 Data;
UINT8 BreakSet = 0;
//
// We assume the UART has been turned on to decode gPort address range
//
//
// Map 5..8 to 0..3
//
Data = (UINT8) (DataBits - (UINT8)5);
//
// Calculate divisor for baud generator
//
Divisor = 115200/(UINTN)BaudRate;
//
// Set communications format
//
OutputData = (UINT8)((DLAB << 7) | ((BreakSet << 6) | ((Parity << 3) | ((StopBits << 2) | Data))));
IoWrite8 (gPort + LCR_OFFSET, OutputData);
//
// Configure baud rate
//
IoWrite8 (gPort + BAUD_HIGH_OFFSET, (UINT8)(Divisor >> 8));
IoWrite8 (gPort + BAUD_LOW_OFFSET, (UINT8)(Divisor & 0xff));
//
// Switch back to bank 0
//
OutputData = (UINT8)((~DLAB<<7)|((BreakSet<<6)|((Parity<<3)|((StopBits<<2)| Data))));
IoWrite8 (gPort + LCR_OFFSET, OutputData);
// Not sure this is the right place to enable the FIFOs....
// We probably need the FIFO enabled to not drop input
IoWrite8 (gPort + FCR_SHADOW_OFFSET, ENABLE_FIFO);
// Configure the UART hardware here
return RETURN_SUCCESS;
}
/**
Check to see if a character is available from GDB. Do not read the character as that is
done via GdbGetChar().
@return TRUE - Character availible
@return FALSE - Character not availible
**/
BOOLEAN
EFIAPI
GdbIsCharAvailable (
VOID
)
{
UINT8 Data;
Data = IoRead8 (gPort + LSR_OFFSET);
return ((Data & LSR_RXDA) == LSR_RXDA);
}
/**
Get a character from GDB. This function must be able to run in interrupt context.
@return A character from GDB
**/
CHAR8
EFIAPI
GdbGetChar (
VOID
)
{
UINT8 Data;
CHAR8 Char;
// Wait for the serial port to be ready
do {
Data = IoRead8 (gPort + LSR_OFFSET);
} while ((Data & LSR_RXDA) == 0);
Char = IoRead8 (gPort);
// Make this an EFI_D_INFO after we get everything debugged.
DEBUG ((EFI_D_ERROR, "<%c<", Char));
return Char;
}
/**
Send a character to GDB. This function must be able to run in interrupt context.
@param Char Send a character to GDB
**/
VOID
EFIAPI
GdbPutChar (
IN CHAR8 Char
)
{
UINT8 Data;
// Make this an EFI_D_INFO after we get everything debugged.
DEBUG ((EFI_D_ERROR, ">%c>", Char));
// Wait for the serial port to be ready
do {
Data = IoRead8 (gPort + LSR_OFFSET);
} while ((Data & LSR_TXRDY) == 0);
IoWrite8 (gPort, Char);
}
/**
Send an ASCII string to GDB. This function must be able to run in interrupt context.
@param String Send a string to GDB
**/
VOID
GdbPutString (
IN CHAR8 *String
)
{
while (*String != '\0') {
GdbPutChar (*String);
String++;
}
}

View File

@@ -0,0 +1,47 @@
#%HEADER%
#/** @file
# Component description file for Base PCI Cf8 Library.
#
# PCI CF8 Library that uses I/O ports 0xCF8 and 0xCFC to perform PCI Configuration cycles.
# Layers on top of an I/O Library instance.
# 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]
INF_VERSION = 0x00010005
BASE_NAME = GdbSerialLib
FILE_GUID = 9999B4EE-081F-4501-AEDC-137A534BAF69
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = GdbSerialLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
CONSTRUCTOR = GdbSerialLibConstructor
[Sources.common]
GdbSerialLib.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
DebugLib
IoLib
[FixedPcd.common]
gEmbeddedTokenSpaceGuid.PcdGdbBaudRate|115200
gEmbeddedTokenSpaceGuid.PcdGdbDataBits|8
gEmbeddedTokenSpaceGuid.PcdGdbParity|1
gEmbeddedTokenSpaceGuid.PcdGdbStopBits|1
gEmbeddedTokenSpaceGuid.PcdGdbUartPort

View File

@@ -0,0 +1,288 @@
/** @file
Generic Capsule services
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 <Common/CapsuleName.h>
//
//Max size capsule services support are platform policy,to populate capsules we just need
//memory to maintain them across reset,it is not a problem. And to special capsules ,for
//example,update flash,it is mostly decided by the platform. Here is a sample size for
//different type capsules.
//
#define MAX_SIZE_POPULATE (0)
#define MAX_SIZE_NON_POPULATE (0)
#define MAX_SUPPORT_CAPSULE_NUM 0x10
BOOLEAN
EFIAPI
SupportUpdateCapsuleRest (
VOID
)
{
//
//If the platform has a way to guarantee the memory integrity across a system reset, return
//TRUE, else FALSE.
//
return FALSE;
}
VOID
EFIAPI
SupportCapsuleSize (
IN OUT UINT32 *MaxSizePopulate,
IN OUT UINT32 *MaxSizeNonPopulate
)
{
//
//Here is a sample size, different platforms have different sizes.
//
*MaxSizePopulate = MAX_SIZE_POPULATE;
*MaxSizeNonPopulate = MAX_SIZE_NON_POPULATE;
return;
}
EFI_STATUS
LibUpdateCapsule (
IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray,
IN UINTN CapsuleCount,
IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
)
/*++
Routine Description:
This code finds if the capsule needs reset to update, if no, update immediately.
Arguments:
CapsuleHeaderArray A array of pointers to capsule headers passed in
CapsuleCount The number of capsule
ScatterGatherList Physical address of datablock list points to capsule
Returns:
EFI STATUS
EFI_SUCCESS Valid capsule was passed.If CAPSULE_FLAG_PERSIT_ACROSS_RESET is
not set, the capsule has been successfully processed by the firmware.
If it set, the ScattlerGatherList is successfully to be set.
EFI_INVALID_PARAMETER CapsuleCount is less than 1,CapsuleGuid is not supported.
EFI_DEVICE_ERROR Failed to SetVariable or AllocatePool or ProcessFirmwareVolume.
--*/
{
UINTN CapsuleSize;
UINTN ArrayNumber;
VOID *BufferPtr;
EFI_STATUS Status;
EFI_HANDLE FvHandle;
UEFI_CAPSULE_HEADER *CapsuleHeader;
if ((CapsuleCount < 1) || (CapsuleCount > MAX_SUPPORT_CAPSULE_NUM)){
return EFI_INVALID_PARAMETER;
}
BufferPtr = NULL;
CapsuleHeader = NULL;
//
//Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET
//and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports.
//
for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
return EFI_INVALID_PARAMETER;
}
if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiCapsuleGuid)) {
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
return EFI_UNSUPPORTED;
}
}
}
//
//Assume that capsules have the same flags on reseting or not.
//
CapsuleHeader = CapsuleHeaderArray[0];
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
//
//Check if the platform supports update capsule across a system reset
//
if (!SupportUpdateCapsuleRest()) {
return EFI_UNSUPPORTED;
}
if (ScatterGatherList == 0) {
return EFI_INVALID_PARAMETER;
} else {
Status = EfiSetVariable (
EFI_CAPSULE_VARIABLE_NAME,
&gEfiCapsuleVendorGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
sizeof (UINTN),
(VOID *) &ScatterGatherList
);
if (Status != EFI_SUCCESS) {
return EFI_DEVICE_ERROR;
}
}
return EFI_SUCCESS;
}
//
//The rest occurs in the condition of non-reset mode
//
if (EfiAtRuntime ()) {
return EFI_INVALID_PARAMETER;
}
//
//Here should be in the boot-time
//
for (ArrayNumber = 0; ArrayNumber < CapsuleCount ; ArrayNumber++) {
CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
CapsuleSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;
Status = gBS->AllocatePool (EfiBootServicesData, CapsuleSize, &BufferPtr);
if (Status != EFI_SUCCESS) {
goto Done;
}
gBS->CopyMem (BufferPtr, (UINT8*)CapsuleHeader+ CapsuleHeader->HeaderSize, CapsuleSize);
//
//Call DXE service ProcessFirmwareVolume to process immediatelly
//
Status = gDS->ProcessFirmwareVolume (BufferPtr, CapsuleSize, &FvHandle);
if (Status != EFI_SUCCESS) {
gBS->FreePool (BufferPtr);
return EFI_DEVICE_ERROR;
}
gDS->Dispatch ();
gBS->FreePool (BufferPtr);
}
return EFI_SUCCESS;
Done:
if (BufferPtr != NULL) {
gBS->FreePool (BufferPtr);
}
return EFI_DEVICE_ERROR;
}
EFI_STATUS
QueryCapsuleCapabilities (
IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray,
IN UINTN CapsuleCount,
OUT UINT64 *MaxiumCapsuleSize,
OUT EFI_RESET_TYPE *ResetType
)
/*++
Routine Description:
This code is query about capsule capability.
Arguments:
CapsuleHeaderArray A array of pointers to capsule headers passed in
CapsuleCount The number of capsule
MaxiumCapsuleSize Max capsule size is supported
ResetType Reset type the capsule indicates, if reset is not needed,return EfiResetCold.
If reset is needed, return EfiResetWarm.
Returns:
EFI STATUS
EFI_SUCCESS Valid answer returned
EFI_INVALID_PARAMETER MaxiumCapsuleSize is NULL,ResetType is NULL.CapsuleCount is less than 1,CapsuleGuid is not supported.
EFI_UNSUPPORTED The capsule type is not supported.
--*/
{
UINTN ArrayNumber;
UEFI_CAPSULE_HEADER *CapsuleHeader;
UINT32 MaxSizePopulate;
UINT32 MaxSizeNonPopulate;
if ((CapsuleCount < 1) || (CapsuleCount > MAX_SUPPORT_CAPSULE_NUM)){
return EFI_INVALID_PARAMETER;
}
if ((MaxiumCapsuleSize == NULL) ||(ResetType == NULL)) {
return EFI_INVALID_PARAMETER;
}
CapsuleHeader = NULL;
//
//Compare GUIDs with EFI_CAPSULE_GUID, if capsule header contains CAPSULE_FLAGS_PERSIST_ACROSS_RESET
//and CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE flags,whatever the GUID is ,the service supports.
//
for (ArrayNumber = 0; ArrayNumber < CapsuleCount; ArrayNumber++) {
CapsuleHeader = CapsuleHeaderArray[ArrayNumber];
if ((CapsuleHeader->Flags & (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)) == CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) {
return EFI_INVALID_PARAMETER;
}
if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gEfiCapsuleGuid)) {
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) == 0) {
return EFI_UNSUPPORTED;
}
}
}
SupportCapsuleSize(&MaxSizePopulate,&MaxSizeNonPopulate);
//
//Assume that capsules have the same flags on reseting or not.
//
CapsuleHeader = CapsuleHeaderArray[0];
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
//
//Check if the platform supports update capsule across a system reset
//
if (!SupportUpdateCapsuleRest()) {
return EFI_UNSUPPORTED;
}
*ResetType = EfiResetWarm;
*MaxiumCapsuleSize = MaxSizePopulate;
} else {
*ResetType = EfiResetCold;
*MaxiumCapsuleSize = MaxSizeNonPopulate;
}
return EFI_SUCCESS;
}
VOID
LibCapsuleVirtualAddressChangeEvent (
VOID
)
{
}
VOID
LibCapsuleInitialize (
VOID
)
{
}

View File

@@ -0,0 +1,226 @@
/** @file
Generic Monotonic Counter services
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.
**/
//
// The current Monotonic count value
//
UINT64 mEfiMtc = 0;
//
// Event to use to update the Mtc's high part when wrapping
//
EFI_EVENT mEfiMtcEvent;
//
// EfiMtcName - Variable name of the MTC value
//
CHAR16 *mEfiMtcName = L"MTC";
//
// EfiMtcGuid - Guid of the MTC value
//
EFI_GUID mEfiMtcGuid = { 0xeb704011, 0x1402, 0x11d3, { 0x8e, 0x77, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } };
//
// Worker functions
//
VOID
EFIAPI
EfiMtcEventHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
Monotonic count event handler. This handler updates the high monotonic count.
Arguments:
Event The event to handle
Context The event context
Returns:
EFI_SUCCESS The event has been handled properly
EFI_NOT_FOUND An error occurred updating the variable.
--*/
{
UINT32 HighCount;
EfiGetNextHighMonotonicCount (&HighCount);
return;
}
VOID
LibMtcVirtualAddressChangeEvent (VOID)
{
}
EFI_STATUS
EFIAPI
LibMtcGetNextHighMonotonicCount (
OUT UINT32 *HighCount
)
{
EFI_STATUS Status;
EFI_TPL OldTpl;
//
// Check input parameters
//
if (HighCount == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!EfiAtRuntime ()) {
// Use a lock if called before ExitBootServices()
OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
}
*HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1;
mEfiMtc = LShiftU64 (*HighCount, 32);
if (!EfiAtRuntime ()) {
gBS->RestoreTPL (OldTpl);
}
//
// Update the NvRam store to match the new high part
//
Status = EfiSetVariable (
mEfiMtcName,
&mEfiMtcGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
sizeof (UINT32),
HighCount
);
return Status;
}
EFI_STATUS
LibMtcGetNextMonotonicCount (
OUT UINT64 *Count
)
{
EFI_STATUS Status;
EFI_TPL OldTpl;
UINT32 HighCount;
UINTN BufferSize;
//
// Can not be called after ExitBootServices()
//
if (EfiAtRuntime ()) {
return EFI_UNSUPPORTED;
}
//
// Check input parameters
//
if (Count == NULL) {
return EFI_INVALID_PARAMETER;
}
if (mEfiMtc == 0) {
//
// If the MTC has not been initialized read the variable
//
//
// Read the last high part
//
BufferSize = sizeof (UINT32);
Status = EfiGetVariable (
mEfiMtcName,
&mEfiMtcGuid,
NULL,
&BufferSize,
&HighCount
);
if (EFI_ERROR (Status)) {
HighCount = 0;
}
//
// Set the current value
//
mEfiMtc = LShiftU64 (HighCount, 32);
//
// Increment the upper 32 bits for this boot
// Continue even if it fails. It will only fail if the variable services are
// not functional.
//
Status = EfiGetNextHighMonotonicCount (&HighCount);
}
//
// Update the monotonic counter with a lock
//
OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
*Count = mEfiMtc;
mEfiMtc++;
gBS->RestoreTPL (OldTpl);
//
// If the MSB bit of the low part toggled, then signal that the high
// part needs updated now
//
if ((((UINT32) mEfiMtc) ^ ((UINT32) *Count)) & 0x80000000) {
gBS->SignalEvent (mEfiMtcEvent);
}
return EFI_SUCCESS;
}
VOID
LibMtcInitialize (
VOID
)
{
EFI_STATUS Status;
//
// Initialize event to handle overflows
//
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL,
EFI_TPL_CALLBACK,
EfiMtcEventHandler,
NULL,
&mEfiMtcEvent
);
ASSERT_EFI_ERROR (Status);
}

View File

@@ -0,0 +1,198 @@
/** @file
Report status code lib on top of either SerialLib and/or EFI Serial Protocol.
Based on PcdStatusCodeUseEfiSerial & PcdStatusCodeUseHardSerial settings
There is just a single runtime memory buffer that contans all the data.
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 "DxeStatusCode.h"
EFI_SERIAL_IO_PROTOCOL *mSerialIoProtocol = NULL;
EFI_STATUS
LibReportStatusCode (
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
IN EFI_GUID *CallerId,
IN EFI_STATUS_CODE_DATA *Data OPTIONAL
)
{
CHAR8 *Filename;
CHAR8 *Description;
CHAR8 *Format;
CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
UINT32 ErrorLevel;
UINT32 LineNumber;
UINTN CharCount;
VA_LIST Marker;
EFI_DEBUG_INFO *DebugInfo;
EFI_TPL CurrentTpl;
if (FeaturePcdGet (PcdStatusCodeUseEfiSerial)) {
if (EfiAtRuntime ()) {
return EFI_DEVICE_ERROR;
}
CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
gBS->RestoreTPL (CurrentTpl);
if (CurrentTpl > EFI_TPL_CALLBACK ) {
return EFI_DEVICE_ERROR;
}
}
Buffer[0] = '\0';
if (Data != NULL &&
ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
//
// Print ASSERT() information into output buffer.
//
CharCount = AsciiSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
"\n\rDXE_ASSERT!: %a (%d): %a\n\r",
Filename,
LineNumber,
Description
);
} else if (Data != NULL &&
ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
//
// Print DEBUG() information into output buffer.
//
CharCount = AsciiVSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
Format,
Marker
);
} else if (Data != NULL &&
CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid) &&
(CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
//
// Print specific data into output buffer.
//
DebugInfo = (EFI_DEBUG_INFO *) (Data + 1);
Marker = (VA_LIST) (DebugInfo + 1);
Format = (CHAR8 *) (((UINT64 *) (DebugInfo + 1)) + 12);
CharCount = AsciiVSPrint (Buffer, EFI_STATUS_CODE_DATA_MAX_SIZE, Format, Marker);
} else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
//
// Print ERROR information into output buffer.
//
CharCount = AsciiSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
"ERROR: C%x:V%x I%x",
CodeType,
Value,
Instance
);
//
// Make sure we don't try to print values that weren't
// intended to be printed, especially NULL GUID pointers.
//
if (CallerId != NULL) {
CharCount += AsciiSPrint (
&Buffer[CharCount - 1],
(EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
" %g",
CallerId
);
}
if (Data != NULL) {
CharCount += AsciiSPrint (
&Buffer[CharCount - 1],
(EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
" %x",
Data
);
}
CharCount += AsciiSPrint (
&Buffer[CharCount - 1],
(EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
"\n\r"
);
} else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
CharCount = AsciiSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
"PROGRESS CODE: V%x I%x\n\r",
Value,
Instance
);
} else {
CharCount = AsciiSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
"Undefined: C%x:V%x I%x\n\r",
CodeType,
Value,
Instance
);
}
if (FeaturePcdGet (PcdStatusCodeUseHardSerial)) {
//
// Callout to SerialPort Lib function to do print.
//
SerialPortWrite ((UINT8 *) Buffer, CharCount);
}
if (FeaturePcdGet (PcdStatusCodeUseEfiSerial)) {
if (mSerialIoProtocol == NULL) {
gBS->LocateProtocol (&gEfiSerialIoProtocolGuid, NULL, (VOID **) &mSerialIoProtocol);
}
if (mSerialIoProtocol == NULL) {
mSerialIoProtocol->Write (
mSerialIoProtocol,
&CharCount,
Buffer
);
}
}
return EFI_SUCCESS;
}
VOID
LibReportStatusCodeVirtualAddressChangeEvent (
VOID
)
{
return;
}
VOID
LibReportStatusCodeInitialize (
VOID
)
{
return;
}

View File

@@ -0,0 +1,63 @@
/** @file
Simple PC Port 0x92 reset driver
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.
**/
VOID
LibResetInitializeReset (
VOID
)
{
}
VOID
LibResetVirtualAddressChangeEvent (
VOID
)
{
}
VOID
LibResetSystem (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN CHAR16 *ResetData OPTIONAL
)
{
UINT8 Data;
switch (ResetType) {
case EfiResetWarm:
case EfiResetCold:
case EfiResetShutdown:
Data = IoRead8 (0x92);
Data |= 1;
IoWrite8 (0x92, Data);
break;
default:
return ;
}
//
// Given we should have reset getting here would be bad
//
ASSERT (FALSE);
}

View File

@@ -0,0 +1,861 @@
/** @file
Simple PC RTC
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.
**/
typedef struct {
EFI_LOCK RtcLock;
UINT16 SavedTimeZone;
UINT8 Daylight;
} PC_RTC_GLOBALS;
#define PCAT_RTC_ADDRESS_REGISTER 0x70
#define PCAT_RTC_DATA_REGISTER 0x71
//
// Dallas DS12C887 Real Time Clock
//
#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59
#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59
#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59
#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59
#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7
#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31
#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12
#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99
#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]
#define RTC_ADDRESS_REGISTER_B 11 // R/W
#define RTC_ADDRESS_REGISTER_C 12 // RO
#define RTC_ADDRESS_REGISTER_D 13 // RO
#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W
//
// Date and time initial values.
// They are used if the RTC values are invalid during driver initialization
//
#define RTC_INIT_SECOND 0
#define RTC_INIT_MINUTE 0
#define RTC_INIT_HOUR 0
#define RTC_INIT_DAY 1
#define RTC_INIT_MONTH 1
#define RTC_INIT_YEAR 2001
//
// Register initial values
//
#define RTC_INIT_REGISTER_A 0x26
#define RTC_INIT_REGISTER_B 0x02
#define RTC_INIT_REGISTER_D 0x0
#pragma pack(1)
//
// Register A
//
typedef struct {
UINT8 RS : 4; // Rate Selection Bits
UINT8 DV : 3; // Divisor
UINT8 UIP : 1; // Update in progress
} RTC_REGISTER_A_BITS;
typedef union {
RTC_REGISTER_A_BITS Bits;
UINT8 Data;
} RTC_REGISTER_A;
//
// Register B
//
typedef struct {
UINT8 DSE : 1; // 0 - Daylight saving disabled 1 - Daylight savings enabled
UINT8 MIL : 1; // 0 - 12 hour mode 1 - 24 hour mode
UINT8 DM : 1; // 0 - BCD Format 1 - Binary Format
UINT8 SQWE : 1; // 0 - Disable SQWE output 1 - Enable SQWE output
UINT8 UIE : 1; // 0 - Update INT disabled 1 - Update INT enabled
UINT8 AIE : 1; // 0 - Alarm INT disabled 1 - Alarm INT Enabled
UINT8 PIE : 1; // 0 - Periodic INT disabled 1 - Periodic INT Enabled
UINT8 SET : 1; // 0 - Normal operation. 1 - Updates inhibited
} RTC_REGISTER_B_BITS;
typedef union {
RTC_REGISTER_B_BITS Bits;
UINT8 Data;
} RTC_REGISTER_B;
//
// Register C
//
typedef struct {
UINT8 Reserved : 4; // Read as zero. Can not be written.
UINT8 UF : 1; // Update End Interrupt Flag
UINT8 AF : 1; // Alarm Interrupt Flag
UINT8 PF : 1; // Periodic Interrupt Flag
UINT8 IRQF : 1; // Iterrupt Request Flag = PF & PIE | AF & AIE | UF & UIE
} RTC_REGISTER_C_BITS;
typedef union {
RTC_REGISTER_C_BITS Bits;
UINT8 Data;
} RTC_REGISTER_C;
//
// Register D
//
typedef struct {
UINT8 Reserved : 7; // Read as zero. Can not be written.
UINT8 VRT : 1; // Valid RAM and Time
} RTC_REGISTER_D_BITS;
typedef union {
RTC_REGISTER_D_BITS Bits;
UINT8 Data;
} RTC_REGISTER_D;
#pragma pack()
PC_RTC_GLOBALS mRtc;
BOOLEAN
IsLeapYear (
IN EFI_TIME *Time
)
{
if (Time->Year % 4 == 0) {
if (Time->Year % 100 == 0) {
if (Time->Year % 400 == 0) {
return TRUE;
} else {
return FALSE;
}
} else {
return TRUE;
}
} else {
return FALSE;
}
}
const INTN mDayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
BOOLEAN
DayValid (
IN EFI_TIME *Time
)
{
if (Time->Day < 1 ||
Time->Day > mDayOfMonth[Time->Month - 1] ||
(Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28))
) {
return FALSE;
}
return TRUE;
}
UINT8
DecimaltoBcd (
IN UINT8 DecValue
)
{
UINTN High;
UINTN Low;
High = DecValue / 10;
Low = DecValue - (High * 10);
return (UINT8) (Low + (High << 4));
}
UINT8
BcdToDecimal (
IN UINT8 BcdValue
)
{
UINTN High;
UINTN Low;
High = BcdValue >> 4;
Low = BcdValue - (High << 4);
return (UINT8) (Low + (High * 10));
}
VOID
ConvertEfiTimeToRtcTime (
IN EFI_TIME *Time,
IN RTC_REGISTER_B RegisterB,
IN UINT8 *Century
)
{
BOOLEAN PM;
PM = TRUE;
//
// Adjust hour field if RTC in in 12 hour mode
//
if (RegisterB.Bits.MIL == 0) {
if (Time->Hour < 12) {
PM = FALSE;
}
if (Time->Hour >= 13) {
Time->Hour = (UINT8) (Time->Hour - 12);
} else if (Time->Hour == 0) {
Time->Hour = 12;
}
}
//
// Set the Time/Date/Daylight Savings values.
//
*Century = DecimaltoBcd ((UINT8) (Time->Year / 100));
Time->Year = (UINT16) (Time->Year % 100);
if (RegisterB.Bits.DM == 0) {
Time->Year = DecimaltoBcd ((UINT8) Time->Year);
Time->Month = DecimaltoBcd (Time->Month);
Time->Day = DecimaltoBcd (Time->Day);
Time->Hour = DecimaltoBcd (Time->Hour);
Time->Minute = DecimaltoBcd (Time->Minute);
Time->Second = DecimaltoBcd (Time->Second);
}
//
// If we are in 12 hour mode and PM is set, then set bit 7 of the Hour field.
//
if (RegisterB.Bits.MIL == 0 && PM) {
Time->Hour = (UINT8) (Time->Hour | 0x80);
}
}
EFI_STATUS
RtcTimeFieldsValid (
IN EFI_TIME *Time
)
/*++
Routine Description:
Arguments:
Returns:
--*/
// TODO: Time - add argument and description to function comment
// TODO: EFI_INVALID_PARAMETER - add return value to function comment
// TODO: EFI_SUCCESS - add return value to function comment
{
if (Time->Year < 1998 ||
Time->Year > 2099 ||
Time->Month < 1 ||
Time->Month > 12 ||
(!DayValid (Time)) ||
Time->Hour > 23 ||
Time->Minute > 59 ||
Time->Second > 59 ||
Time->Nanosecond > 999999999 ||
(!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) ||
(Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))
) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
UINT8
RtcRead (
IN UINT8 Address
)
{
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
return IoRead8 (PCAT_RTC_DATA_REGISTER);
}
VOID
RtcWrite (
IN UINT8 Address,
IN UINT8 Data
)
{
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, (UINT8) (Address | (UINT8) (IoRead8 (PCAT_RTC_ADDRESS_REGISTER) & 0x80)));
IoWrite8 (PCAT_RTC_DATA_REGISTER, Data);
}
EFI_STATUS
RtcTestCenturyRegister (
VOID
)
{
UINT8 Century;
UINT8 Temp;
Century = RtcRead (RTC_ADDRESS_CENTURY);
//
// RtcWrite (RTC_ADDRESS_CENTURY, 0x00);
//
Temp = (UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f);
RtcWrite (RTC_ADDRESS_CENTURY, Century);
if (Temp == 0x19 || Temp == 0x20) {
return EFI_SUCCESS;
}
return EFI_DEVICE_ERROR;
}
VOID
ConvertRtcTimeToEfiTime (
IN EFI_TIME *Time,
IN RTC_REGISTER_B RegisterB
)
{
BOOLEAN PM;
if ((Time->Hour) & 0x80) {
PM = TRUE;
} else {
PM = FALSE;
}
Time->Hour = (UINT8) (Time->Hour & 0x7f);
if (RegisterB.Bits.DM == 0) {
Time->Year = BcdToDecimal ((UINT8) Time->Year);
Time->Month = BcdToDecimal (Time->Month);
Time->Day = BcdToDecimal (Time->Day);
Time->Hour = BcdToDecimal (Time->Hour);
Time->Minute = BcdToDecimal (Time->Minute);
Time->Second = BcdToDecimal (Time->Second);
}
//
// If time is in 12 hour format, convert it to 24 hour format
//
if (RegisterB.Bits.MIL == 0) {
if (PM && Time->Hour < 12) {
Time->Hour = (UINT8) (Time->Hour + 12);
}
if (!PM && Time->Hour == 12) {
Time->Hour = 0;
}
}
Time->Nanosecond = 0;
Time->TimeZone = EFI_UNSPECIFIED_TIMEZONE;
Time->Daylight = 0;
}
EFI_STATUS
RtcWaitToUpdate (
UINTN Timeout
)
{
RTC_REGISTER_A RegisterA;
RTC_REGISTER_D RegisterD;
//
// See if the RTC is functioning correctly
//
RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
if (RegisterD.Bits.VRT == 0) {
return EFI_DEVICE_ERROR;
}
//
// Wait for up to 0.1 seconds for the RTC to be ready.
//
Timeout = (Timeout / 10) + 1;
RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
while (RegisterA.Bits.UIP == 1 && Timeout > 0) {
MicroSecondDelay (10);
RegisterA.Data = RtcRead (RTC_ADDRESS_REGISTER_A);
Timeout--;
}
RegisterD.Data = RtcRead (RTC_ADDRESS_REGISTER_D);
if (Timeout == 0 || RegisterD.Bits.VRT == 0) {
return EFI_DEVICE_ERROR;
}
return EFI_SUCCESS;
}
EFI_STATUS
LibGetTime (
OUT EFI_TIME *Time,
OUT EFI_TIME_CAPABILITIES *Capabilities
)
{
EFI_STATUS Status;
RTC_REGISTER_B RegisterB;
UINT8 Century;
UINTN BufferSize;
//
// Check parameters for null pointer
//
if (Time == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Acquire RTC Lock to make access to RTC atomic
//
EfiAcquireLock (&mRtc.RtcLock);
//
// Wait for up to 0.1 seconds for the RTC to be updated
//
Status = RtcWaitToUpdate (100000);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mRtc.RtcLock);
return Status;
}
//
// Read Register B
//
RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
//
// Get the Time/Date/Daylight Savings values.
//
Time->Second = RtcRead (RTC_ADDRESS_SECONDS);
Time->Minute = RtcRead (RTC_ADDRESS_MINUTES);
Time->Hour = RtcRead (RTC_ADDRESS_HOURS);
Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
Time->Month = RtcRead (RTC_ADDRESS_MONTH);
Time->Year = RtcRead (RTC_ADDRESS_YEAR);
ConvertRtcTimeToEfiTime (Time, RegisterB);
if (RtcTestCenturyRegister () == EFI_SUCCESS) {
Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));
} else {
Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));
}
Time->Year = (UINT16) (Century * 100 + Time->Year);
//
// Release RTC Lock.
//
EfiReleaseLock (&mRtc.RtcLock);
//
// Get the variable that containts the TimeZone and Daylight fields
//
Time->TimeZone = mRtc.SavedTimeZone;
Time->Daylight = mRtc.Daylight;
BufferSize = sizeof (INT16) + sizeof (UINT8);
//
// Make sure all field values are in correct range
//
Status = RtcTimeFieldsValid (Time);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
//
// Fill in Capabilities if it was passed in
//
if (Capabilities) {
Capabilities->Resolution = 1;
//
// 1 hertz
//
Capabilities->Accuracy = 50000000;
//
// 50 ppm
//
Capabilities->SetsToZero = FALSE;
}
return EFI_SUCCESS;
}
EFI_STATUS
LibSetTime (
IN EFI_TIME *Time
)
{
EFI_STATUS Status;
EFI_TIME RtcTime;
RTC_REGISTER_B RegisterB;
UINT8 Century;
if (Time == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Make sure that the time fields are valid
//
Status = RtcTimeFieldsValid (Time);
if (EFI_ERROR (Status)) {
return Status;
}
CopyMem (&RtcTime, Time, sizeof (EFI_TIME));
//
// Acquire RTC Lock to make access to RTC atomic
//
EfiAcquireLock (&mRtc.RtcLock);
//
// Wait for up to 0.1 seconds for the RTC to be updated
//
Status = RtcWaitToUpdate (100000);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mRtc.RtcLock);
return Status;
}
//
// Read Register B, and inhibit updates of the RTC
//
RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
RegisterB.Bits.SET = 1;
RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);
RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);
RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);
RtcWrite (RTC_ADDRESS_HOURS, RtcTime.Hour);
RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);
RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);
RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year);
if (RtcTestCenturyRegister () == EFI_SUCCESS) {
Century = (UINT8) ((Century & 0x7f) | (RtcRead (RTC_ADDRESS_CENTURY) & 0x80));
}
RtcWrite (RTC_ADDRESS_CENTURY, Century);
//
// Allow updates of the RTC registers
//
RegisterB.Bits.SET = 0;
RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
//
// Release RTC Lock.
//
EfiReleaseLock (&mRtc.RtcLock);
//
// Set the variable that containts the TimeZone and Daylight fields
//
mRtc.SavedTimeZone = Time->TimeZone;
mRtc.Daylight = Time->Daylight;
return Status;
}
EFI_STATUS
libGetWakeupTime (
OUT BOOLEAN *Enabled,
OUT BOOLEAN *Pending,
OUT EFI_TIME *Time
)
{
EFI_STATUS Status;
RTC_REGISTER_B RegisterB;
RTC_REGISTER_C RegisterC;
UINT8 Century;
//
// Check paramters for null pointers
//
if ((Enabled == NULL) || (Pending == NULL) || (Time == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Acquire RTC Lock to make access to RTC atomic
//
EfiAcquireLock (&mRtc.RtcLock);
//
// Wait for up to 0.1 seconds for the RTC to be updated
//
Status = RtcWaitToUpdate (100000);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mRtc.RtcLock);
return EFI_DEVICE_ERROR;
}
//
// Read Register B and Register C
//
RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);
//
// Get the Time/Date/Daylight Savings values.
//
*Enabled = RegisterB.Bits.AIE;
if (*Enabled) {
Time->Second = RtcRead (RTC_ADDRESS_SECONDS_ALARM);
Time->Minute = RtcRead (RTC_ADDRESS_MINUTES_ALARM);
Time->Hour = RtcRead (RTC_ADDRESS_HOURS_ALARM);
Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
Time->Month = RtcRead (RTC_ADDRESS_MONTH);
Time->Year = RtcRead (RTC_ADDRESS_YEAR);
} else {
Time->Second = 0;
Time->Minute = 0;
Time->Hour = 0;
Time->Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
Time->Month = RtcRead (RTC_ADDRESS_MONTH);
Time->Year = RtcRead (RTC_ADDRESS_YEAR);
}
ConvertRtcTimeToEfiTime (Time, RegisterB);
if (RtcTestCenturyRegister () == EFI_SUCCESS) {
Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));
} else {
Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));
}
Time->Year = (UINT16) (Century * 100 + Time->Year);
//
// Release RTC Lock.
//
EfiReleaseLock (&mRtc.RtcLock);
//
// Make sure all field values are in correct range
//
Status = RtcTimeFieldsValid (Time);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
*Pending = RegisterC.Bits.AF;
return EFI_SUCCESS;
}
EFI_STATUS
LibSetWakeupTime (
IN BOOLEAN Enabled,
OUT EFI_TIME *Time
)
{
EFI_STATUS Status;
EFI_TIME RtcTime;
RTC_REGISTER_B RegisterB;
UINT8 Century;
EFI_TIME_CAPABILITIES Capabilities;
if (Enabled) {
if (Time == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Make sure that the time fields are valid
//
Status = RtcTimeFieldsValid (Time);
if (EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
//
// Just support set alarm time within 24 hours
//
LibGetTime (&RtcTime, &Capabilities);
if (Time->Year != RtcTime.Year ||
Time->Month != RtcTime.Month ||
(Time->Day != RtcTime.Day && Time->Day != (RtcTime.Day + 1))
) {
return EFI_UNSUPPORTED;
}
//
// Make a local copy of the time and date
//
CopyMem (&RtcTime, Time, sizeof (EFI_TIME));
}
//
// Acquire RTC Lock to make access to RTC atomic
//
EfiAcquireLock (&mRtc.RtcLock);
//
// Wait for up to 0.1 seconds for the RTC to be updated
//
Status = RtcWaitToUpdate (100000);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mRtc.RtcLock);
return EFI_DEVICE_ERROR;
}
//
// Read Register B, and inhibit updates of the RTC
//
RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
RegisterB.Bits.SET = 1;
RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
if (Enabled) {
ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);
//
// Set RTC alarm time
//
RtcWrite (RTC_ADDRESS_SECONDS_ALARM, RtcTime.Second);
RtcWrite (RTC_ADDRESS_MINUTES_ALARM, RtcTime.Minute);
RtcWrite (RTC_ADDRESS_HOURS_ALARM, RtcTime.Hour);
RegisterB.Bits.AIE = 1;
} else {
RegisterB.Bits.AIE = 0;
}
//
// Allow updates of the RTC registers
//
RegisterB.Bits.SET = 0;
RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
//
// Release RTC Lock.
//
EfiReleaseLock (&mRtc.RtcLock);
return EFI_SUCCESS;
}
VOID
LibRtcVirtualAddressChangeEvent (
VOID
)
{
}
VOID
LibRtcInitialize (
VOID
)
{
EFI_STATUS Status;
RTC_REGISTER_A RegisterA;
RTC_REGISTER_B RegisterB;
RTC_REGISTER_C RegisterC;
RTC_REGISTER_D RegisterD;
UINT8 Century;
EFI_TIME Time;
//
// Acquire RTC Lock to make access to RTC atomic
//
EfiAcquireLock (&mRtc.RtcLock);
//
// Initialize RTC Register
//
// Make sure Division Chain is properly configured,
// or RTC clock won't "tick" -- time won't increment
//
RegisterA.Data = RTC_INIT_REGISTER_A;
RtcWrite (RTC_ADDRESS_REGISTER_A, RegisterA.Data);
//
// Read Register B
//
RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);
//
// Clear RTC flag register
//
RegisterC.Data = RtcRead (RTC_ADDRESS_REGISTER_C);
//
// Clear RTC register D
//
RegisterD.Data = RTC_INIT_REGISTER_D;
RtcWrite (RTC_ADDRESS_REGISTER_D, RegisterD.Data);
//
// Wait for up to 0.1 seconds for the RTC to be updated
//
Status = RtcWaitToUpdate (100000);
if (EFI_ERROR (Status)) {
EfiReleaseLock (&mRtc.RtcLock);
return;
}
//
// Get the Time/Date/Daylight Savings values.
//
Time.Second = RtcRead (RTC_ADDRESS_SECONDS);
Time.Minute = RtcRead (RTC_ADDRESS_MINUTES);
Time.Hour = RtcRead (RTC_ADDRESS_HOURS);
Time.Day = RtcRead (RTC_ADDRESS_DAY_OF_THE_MONTH);
Time.Month = RtcRead (RTC_ADDRESS_MONTH);
Time.Year = RtcRead (RTC_ADDRESS_YEAR);
ConvertRtcTimeToEfiTime (&Time, RegisterB);
if (RtcTestCenturyRegister () == EFI_SUCCESS) {
Century = BcdToDecimal ((UINT8) (RtcRead (RTC_ADDRESS_CENTURY) & 0x7f));
} else {
Century = BcdToDecimal (RtcRead (RTC_ADDRESS_CENTURY));
}
Time.Year = (UINT16) (Century * 100 + Time.Year);
//
// Set RTC configuration after get original time
//
RtcWrite (RTC_ADDRESS_REGISTER_B, RTC_INIT_REGISTER_B);
//
// Release RTC Lock.
//
EfiReleaseLock (&mRtc.RtcLock);
//
// Validate time fields
//
Status = RtcTimeFieldsValid (&Time);
if (EFI_ERROR (Status)) {
Time.Second = RTC_INIT_SECOND;
Time.Minute = RTC_INIT_MINUTE;
Time.Hour = RTC_INIT_HOUR;
Time.Day = RTC_INIT_DAY;
Time.Month = RTC_INIT_MONTH;
Time.Year = RTC_INIT_YEAR;
}
//
// Reset time value according to new RTC configuration
//
LibSetTime (&Time);
return;
}

View File

@@ -0,0 +1,306 @@
/** @file
Variable services implemented from system memory
There is just a single runtime memory buffer that contans all the data.
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.
**/
UINT64 mMaximumVariableStorageSize;
UINT64 mRemainingVariableStorageSize;
UINT64 mMaximumVariableSize;
typedef struct {
EFI_GUID VendorGuid;
UINT32 Attribute;
UINTN DataSize;
} VARIABLE_ARRAY_ENTRY;
// CHAR16 VariableName[]
// UINT8 Data[]
VARIABLE_ARRAY_ENTRY *mVariableArray = NULL;
VARIABLE_ARRAY_ENTRY *mVariableArrayNextFree = NULL;
VARIABLE_ARRAY_ENTRY *mVariableArrayEnd = NULL;
VARIABLE_ARRAY_ENTRY *
AddEntry (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
UINTN Size;
UINTN SizeOfString;
VARIABLE_ARRAY_ENTRY *Entry;
EFI_TPL CurrentTpl;
SizeOfString = StrSize (VariableName);
Size = SizeOfString + sizeof (VARIABLE_ARRAY_ENTRY) + DataSize;
if ((VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + Size) > mVariableArrayEnd) {
// ran out of space
return NULL;
}
if (!EfiAtRuntime ()) {
// Enter critical section
CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
}
Entry = mVariableArrayNextFree;
CopyGuid (&Entry->VendorGuid, VendorGuid);
Entry->Attribute = Attributes;
Entry->DataSize = DataSize;
StrCpy ((CHAR16 *)++mVariableArrayNextFree, VariableName);
mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + SizeOfString);
CopyMem (mVariableArrayNextFree, Data, DataSize);
mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) + DataSize);
if (!EfiAtRuntime ()) {
// Exit Critical section
gBS->RestoreTPL (CurrentTpl);
}
return Entry;
}
VOID
DeleteEntry (
IN VARIABLE_ARRAY_ENTRY *Entry
)
{
UINTN Size;
UINT8 *Data;
EFI_TPL CurrentTpl;
Size = StrSize ((CHAR16 *)(Entry + 1)) + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize;
Data = ((UINT8 *)Entry) + Size;
CopyMem (Entry, Data, (UINTN)mVariableArrayNextFree - (UINTN)Data);
if (!EfiAtRuntime ()) {
// Enter critical section
CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
}
mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArrayNextFree) - Size);
if (!EfiAtRuntime ()) {
// Exit Critical section
gBS->RestoreTPL (CurrentTpl);
}
}
VARIABLE_ARRAY_ENTRY *
GetVariableArrayEntry (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT VOID **Data OPTIONAL
)
{
VARIABLE_ARRAY_ENTRY *Entry;
UINTN Size;
if (*VariableName == L'\0') {
// by definition first entry is null-terminated string
if (mVariableArray == mVariableArrayNextFree) {
return NULL;
}
return mVariableArray;
}
for (Entry = mVariableArray; Entry < mVariableArrayEnd;) {
if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {
if (StrCmp (VariableName, (CHAR16 *)(Entry + 1))) {
Size = StrSize ((CHAR16 *)(Entry + 1));
if (Data != NULL) {
*Data = (VOID *)(((UINT8 *)Entry) + (Size + sizeof (VARIABLE_ARRAY_ENTRY)));
}
return Entry;
}
}
Size = StrSize ((CHAR16 *)(Entry + 1)) + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize;
Entry = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)Entry) + Size);
}
return NULL;
}
EFI_STATUS
LibGetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT UINT32 *Attributes OPTIONAL,
IN OUT UINTN *DataSize,
OUT VOID *Data
)
{
VARIABLE_ARRAY_ENTRY *Entry;
VOID *InternalData;
if (EfiAtRuntime () && (Attributes != NULL)) {
if ((*Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {
return EFI_NOT_FOUND;
}
}
Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData);
if (Entry == NULL) {
return EFI_NOT_FOUND;
}
if (*DataSize < Entry->DataSize) {
*DataSize = Entry->DataSize;
return EFI_BUFFER_TOO_SMALL;
}
*DataSize = Entry->DataSize;
if (Attributes != NULL) {
*Attributes = Entry->Attribute;
}
CopyMem (Data, InternalData, *DataSize);
return EFI_SUCCESS;
}
EFI_STATUS
LibGetNextVariableName (
IN OUT UINTN *VariableNameSize,
IN OUT CHAR16 *VariableName,
IN OUT EFI_GUID *VendorGuid
)
{
VARIABLE_ARRAY_ENTRY *Entry;
VOID *InternalData;
UINTN StringSize;
BOOLEAN Done;
for (Done = FALSE; !Done; ) {
Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData);
if (Entry == NULL) {
return EFI_NOT_FOUND;
}
// If we are at runtime skip variables that do not have the Runitme attribute set.
Done = (EfiAtRuntime () && ((Entry->Attribute & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) ? FALSE : TRUE;
}
StringSize = StrSize ((CHAR16 *)(Entry + 1));
Entry = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)Entry) + (StringSize + sizeof (VARIABLE_ARRAY_ENTRY) + Entry->DataSize));
if (Entry >= mVariableArrayEnd) {
return EFI_NOT_FOUND;
}
if (*VariableNameSize < StringSize) {
*VariableNameSize = StringSize;
return EFI_BUFFER_TOO_SMALL;
}
*VariableNameSize = StringSize;
CopyMem (VariableName, (CHAR16 *)(Entry + 1), StringSize);
CopyMem (VendorGuid, &Entry->VendorGuid, sizeof (EFI_GUID));
return EFI_SUCCESS;
}
EFI_STATUS
LibSetVariable (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
IN UINT32 Attributes,
IN UINTN DataSize,
IN VOID *Data
)
{
VARIABLE_ARRAY_ENTRY *Entry;
VOID *InternalData;
if (EfiAtRuntime () && ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
return EFI_NOT_FOUND;
}
Entry = GetVariableArrayEntry (VariableName, VendorGuid, &InternalData);
if (Entry == NULL) {
if (DataSize == 0) {
return EFI_NOT_FOUND;
}
Entry = AddEntry (VariableName, VendorGuid, Attributes, DataSize, Data);
return (Entry == NULL) ? EFI_OUT_OF_RESOURCES : EFI_SUCCESS;
} else if (DataSize == 0) {
// DataSize is zero so delete
DeleteEntry (Entry);
} else if (DataSize == Entry->DataSize) {
// No change is size so just update the store
Entry->Attribute |= Attributes;
CopyMem (InternalData, Data, DataSize);
} else {
// Grow the entry by deleting and adding back. Don't lose previous Attributes
Attributes |= Entry->Attribute;
DeleteEntry (Entry);
Entry = AddEntry (VariableName, VendorGuid, Attributes, DataSize, Data);
return (Entry == NULL) ? EFI_OUT_OF_RESOURCES : EFI_SUCCESS;
}
}
EFI_STATUS
LibQueryVariableInfo (
IN UINT32 Attributes,
OUT UINT64 *MaximumVariableStorageSize,
OUT UINT64 *RemainingVariableStorageSize,
OUT UINT64 *MaximumVariableSize
)
{
*MaximumVariableStorageSize = mMaximumVariableStorageSize;
*RemainingVariableStorageSize = mRemainingVariableStorageSize;
*MaximumVariableStorageSize = mRemainingVariableStorageSize;
return EFI_SUCCESS;
}
VOID
LibVariableVirtualAddressChangeEvent (VOID)
{
EfiConvertPointer (0, (VOID **)&mVariableArray);
EfiConvertPointer (0, (VOID **)&mVariableArrayNextFree);
EfiConvertPointer (0, (VOID **)&mVariableArrayEnd);
}
VOID
LibVariableInitialize (VOID)
{
UINTN Size;
Size = PcdGet32 (PcdEmbeddedMemVariableStoreSize);
mVariableArray = mVariableArrayNextFree = (VARIABLE_ARRAY_ENTRY *)AllocateRuntimePool (Size);
ASSERT (mVariableArray != NULL);
mVariableArrayEnd = (VARIABLE_ARRAY_ENTRY *)(((UINT8 *)mVariableArray) + Size);
mMaximumVariableStorageSize = Size - sizeof (VARIABLE_ARRAY_ENTRY);
mRemainingVariableStorageSize = mMaximumVariableStorageSize;
mMaximumVariableSize = mMaximumVariableStorageSize;
}

View File

@@ -0,0 +1,247 @@
/** @file
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 <PiPei.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/ExtractGuidedSectionLib.h>
#include <Library/PcdLib.h>
#include <Library/PrePiLib.h>
#define PRE_PI_EXTRACT_GUIDED_SECTION_DATA_GUID { 0x385A982C, 0x2F49, 0x4043, { 0xA5, 0x1E, 0x49, 0x01, 0x02, 0x5C, 0x8B, 0x6B }}
typedef struct {
UINT32 NumberOfExtractHandler;
GUID *ExtractHandlerGuidTable;
EXTRACT_GUIDED_SECTION_DECODE_HANDLER *ExtractDecodeHandlerTable;
EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *ExtractGetInfoHandlerTable;
} PRE_PI_EXTRACT_GUIDED_SECTION_DATA;
PRE_PI_EXTRACT_GUIDED_SECTION_DATA *
GetSavedData (
VOID
)
{
EFI_HOB_GUID_TYPE *GuidHob;
GUID SavedDataGuid = PRE_PI_EXTRACT_GUIDED_SECTION_DATA_GUID;
GuidHob = GetFirstGuidHob(&SavedDataGuid);
GuidHob++;
return (PRE_PI_EXTRACT_GUIDED_SECTION_DATA *)GuidHob;
}
RETURN_STATUS
EFIAPI
ExtractGuidedSectionRegisterHandlers (
IN CONST GUID *SectionGuid,
IN EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER GetInfoHandler,
IN EXTRACT_GUIDED_SECTION_DECODE_HANDLER DecodeHandler
)
{
PRE_PI_EXTRACT_GUIDED_SECTION_DATA *SavedData;
UINT32 Index;
//
// Check input paramter.
//
if (SectionGuid == NULL) {
return RETURN_INVALID_PARAMETER;
}
SavedData = GetSavedData();
//
// Search the match registered GetInfo handler for the input guided section.
//
for (Index = 0; Index < SavedData->NumberOfExtractHandler; Index ++) {
if (CompareGuid (&SavedData->ExtractHandlerGuidTable[Index], SectionGuid)) {
break;
}
}
//
// If the guided handler has been registered before, only update its handler.
//
if (Index < SavedData->NumberOfExtractHandler) {
SavedData->ExtractDecodeHandlerTable [Index] = DecodeHandler;
SavedData->ExtractGetInfoHandlerTable [Index] = GetInfoHandler;
return RETURN_SUCCESS;
}
//
// Check the global table is enough to contain new Handler.
//
if (SavedData->NumberOfExtractHandler >= PcdGet32 (PcdMaximumGuidedExtractHandler)) {
return RETURN_OUT_OF_RESOURCES;
}
//
// Register new Handler and guid value.
//
CopyGuid (&SavedData->ExtractHandlerGuidTable [SavedData->NumberOfExtractHandler], SectionGuid);
SavedData->ExtractDecodeHandlerTable [SavedData->NumberOfExtractHandler] = DecodeHandler;
SavedData->ExtractGetInfoHandlerTable [SavedData->NumberOfExtractHandler++] = GetInfoHandler;
return RETURN_SUCCESS;
}
UINTN
EFIAPI
ExtractGuidedSectionGetGuidList (
IN OUT GUID **ExtractHandlerGuidTable
)
{
PRE_PI_EXTRACT_GUIDED_SECTION_DATA *SavedData;
ASSERT(ExtractHandlerGuidTable != NULL);
SavedData = GetSavedData();
*ExtractHandlerGuidTable = SavedData->ExtractHandlerGuidTable;
return SavedData->NumberOfExtractHandler;
}
RETURN_STATUS
EFIAPI
ExtractGuidedSectionGetInfo (
IN CONST VOID *InputSection,
OUT UINT32 *OutputBufferSize,
OUT UINT32 *ScratchBufferSize,
OUT UINT16 *SectionAttribute
)
{
PRE_PI_EXTRACT_GUIDED_SECTION_DATA *SavedData;
UINT32 Index;
if (InputSection == NULL) {
return RETURN_INVALID_PARAMETER;
}
ASSERT (OutputBufferSize != NULL);
ASSERT (ScratchBufferSize != NULL);
ASSERT (SectionAttribute != NULL);
SavedData = GetSavedData();
//
// Search the match registered GetInfo handler for the input guided section.
//
for (Index = 0; Index < SavedData->NumberOfExtractHandler; Index ++) {
if (CompareGuid (&SavedData->ExtractHandlerGuidTable[Index], &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
break;
}
}
//
// Not found, the input guided section is not supported.
//
if (Index == SavedData->NumberOfExtractHandler) {
return RETURN_INVALID_PARAMETER;
}
//
// Call the match handler to getinfo for the input section data.
//
return SavedData->ExtractGetInfoHandlerTable [Index] (
InputSection,
OutputBufferSize,
ScratchBufferSize,
SectionAttribute
);
}
RETURN_STATUS
EFIAPI
ExtractGuidedSectionDecode (
IN CONST VOID *InputSection,
OUT VOID **OutputBuffer,
OUT VOID *ScratchBuffer, OPTIONAL
OUT UINT32 *AuthenticationStatus
)
{
PRE_PI_EXTRACT_GUIDED_SECTION_DATA *SavedData;
UINT32 Index;
if (InputSection == NULL) {
return RETURN_INVALID_PARAMETER;
}
ASSERT (OutputBuffer != NULL);
ASSERT (AuthenticationStatus != NULL);
SavedData = GetSavedData();
//
// Search the match registered GetInfo handler for the input guided section.
//
for (Index = 0; Index < SavedData->NumberOfExtractHandler; Index ++) {
if (CompareGuid (&SavedData->ExtractHandlerGuidTable[Index], &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
break;
}
}
//
// Not found, the input guided section is not supported.
//
if (Index == SavedData->NumberOfExtractHandler) {
return RETURN_INVALID_PARAMETER;
}
//
// Call the match handler to getinfo for the input section data.
//
return SavedData->ExtractDecodeHandlerTable [Index] (
InputSection,
OutputBuffer,
ScratchBuffer,
AuthenticationStatus
);
}
RETURN_STATUS
EFIAPI
ExtractGuidedSectionLibConstructor (
VOID
)
{
PRE_PI_EXTRACT_GUIDED_SECTION_DATA SavedData;
GUID HobGuid = PRE_PI_EXTRACT_GUIDED_SECTION_DATA_GUID;
//
// Allocate global pool space to store the registered handler and its guid value.
//
SavedData.ExtractHandlerGuidTable = (GUID *)AllocatePool(PcdGet32(PcdMaximumGuidedExtractHandler) * sizeof(GUID));
if (SavedData.ExtractHandlerGuidTable == NULL) {
return RETURN_OUT_OF_RESOURCES;
}
SavedData.ExtractDecodeHandlerTable = (EXTRACT_GUIDED_SECTION_DECODE_HANDLER *)AllocatePool(PcdGet32(PcdMaximumGuidedExtractHandler) * sizeof(EXTRACT_GUIDED_SECTION_DECODE_HANDLER));
if (SavedData.ExtractDecodeHandlerTable == NULL) {
return RETURN_OUT_OF_RESOURCES;
}
SavedData.ExtractGetInfoHandlerTable = (EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER *)AllocatePool(PcdGet32(PcdMaximumGuidedExtractHandler) * sizeof(EXTRACT_GUIDED_SECTION_GET_INFO_HANDLER));
if (SavedData.ExtractGetInfoHandlerTable == NULL) {
return RETURN_OUT_OF_RESOURCES;
}
//
// the initialized number is Zero.
//
SavedData.NumberOfExtractHandler = 0;
BuildGuidDataHob(&HobGuid, &SavedData, sizeof(SavedData));
return RETURN_SUCCESS;
}

View File

@@ -0,0 +1,24 @@
#%HEADER%
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PrePiExtractGuidedSectionLib
FILE_GUID = 36F6E94E-6E8E-488E-89A4-7AD911C5AFB1
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = ExtractGuidedSectionLib
CONSTRUCTOR = ExtractGuidedSectionLibConstructor
[Sources.common]
PrePiExtractGuidedSectionLib.c
[Packages]
EmbeddedPkg/EmbeddedPkg.dec
MdePkg/MdePkg.dec
[LibraryClasses]
BaseMemoryLib
DebugLib
[FixedPcd.common]
gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler

View File

@@ -0,0 +1,841 @@
/** @file
Implementation of the 6 PEI Ffs (FV) APIs in library form.
This code only knows about a FV if it has a EFI_HOB_TYPE_FV entry in the HOB list
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 <PrePi.h>
#include <Library/ExtractGuidedSectionLib.h>
#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
(ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
/**
Returns the highest bit set of the State field
@param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
in the Attributes field.
@param FfsHeader Pointer to FFS File Header
@retval the highest bit in the State field
**/
STATIC
EFI_FFS_FILE_STATE
GetFileState(
IN UINT8 ErasePolarity,
IN EFI_FFS_FILE_HEADER *FfsHeader
)
{
EFI_FFS_FILE_STATE FileState;
EFI_FFS_FILE_STATE HighestBit;
FileState = FfsHeader->State;
if (ErasePolarity != 0) {
FileState = (EFI_FFS_FILE_STATE)~FileState;
}
HighestBit = 0x80;
while (HighestBit != 0 && (HighestBit & FileState) == 0) {
HighestBit >>= 1;
}
return HighestBit;
}
/**
Calculates the checksum of the header of a file.
The header is a zero byte checksum, so zero means header is good
@param FfsHeader Pointer to FFS File Header
@retval Checksum of the header
**/
STATIC
UINT8
CalculateHeaderChecksum (
IN EFI_FFS_FILE_HEADER *FileHeader
)
{
UINT8 *Ptr;
UINTN Index;
UINT8 Sum;
Sum = 0;
Ptr = (UINT8 *)FileHeader;
for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) {
Sum = (UINT8)(Sum + Ptr[Index]);
Sum = (UINT8)(Sum + Ptr[Index+1]);
Sum = (UINT8)(Sum + Ptr[Index+2]);
Sum = (UINT8)(Sum + Ptr[Index+3]);
}
for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) {
Sum = (UINT8)(Sum + Ptr[Index]);
}
//
// State field (since this indicates the different state of file).
//
Sum = (UINT8)(Sum - FileHeader->State);
//
// Checksum field of the file is not part of the header checksum.
//
Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File);
return Sum;
}
/**
Given a FileHandle return the VolumeHandle
@param FileHandle File handle to look up
@param VolumeHandle Match for FileHandle
@retval TRUE VolumeHandle is valid
**/
STATIC
BOOLEAN
EFIAPI
FileHandleToVolume (
IN EFI_PEI_FILE_HANDLE FileHandle,
OUT EFI_PEI_FV_HANDLE *VolumeHandle
)
{
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
EFI_PEI_HOB_POINTERS Hob;
Hob.Raw = GetHobList ();
if (Hob.Raw == NULL) {
return FALSE;
}
do {
Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw);
if (Hob.Raw != NULL) {
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(Hob.FirmwareVolume->BaseAddress);
if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) && \
((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {
*VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader;
return TRUE;
}
Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob));
}
} while (Hob.Raw != NULL);
return FALSE;
}
/**
Given the input file pointer, search for the next matching file in the
FFS volume as defined by SearchType. The search starts from FileHeader inside
the Firmware Volume defined by FwVolHeader.
@param FileHandle File handle to look up
@param VolumeHandle Match for FileHandle
**/
EFI_STATUS
FindFileEx (
IN CONST EFI_PEI_FV_HANDLE FvHandle,
IN CONST EFI_GUID *FileName, OPTIONAL
IN EFI_FV_FILETYPE SearchType,
IN OUT EFI_PEI_FILE_HANDLE *FileHandle
)
{
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
EFI_FFS_FILE_HEADER **FileHeader;
EFI_FFS_FILE_HEADER *FfsFileHeader;
EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;
UINT32 FileLength;
UINT32 FileOccupiedSize;
UINT32 FileOffset;
UINT64 FvLength;
UINT8 ErasePolarity;
UINT8 FileState;
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle;
FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle;
FvLength = FwVolHeader->FvLength;
if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
ErasePolarity = 1;
} else {
ErasePolarity = 0;
}
//
// If FileHeader is not specified (NULL) or FileName is not NULL,
// start with the first file in the firmware volume. Otherwise,
// start from the FileHeader.
//
if ((*FileHeader == NULL) || (FileName != NULL)) {
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
if (FwVolHeader->ExtHeaderOffset != 0) {
FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset);
FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize);
}
} else {
//
// Length is 24 bits wide so mask upper 8 bits
// FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
//
FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;
FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);
}
FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);
ASSERT (FileOffset <= 0xFFFFFFFF);
while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
//
// Get FileState which is the highest bit of the State
//
FileState = GetFileState (ErasePolarity, FfsFileHeader);
switch (FileState) {
case EFI_FILE_HEADER_INVALID:
FileOffset += sizeof(EFI_FFS_FILE_HEADER);
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));
break;
case EFI_FILE_DATA_VALID:
case EFI_FILE_MARKED_FOR_UPDATE:
if (CalculateHeaderChecksum (FfsFileHeader) != 0) {
ASSERT (FALSE);
*FileHeader = NULL;
return EFI_NOT_FOUND;
}
FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
if (FileName != NULL) {
if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) {
*FileHeader = FfsFileHeader;
return EFI_SUCCESS;
}
} else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) &&
(FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) {
*FileHeader = FfsFileHeader;
return EFI_SUCCESS;
}
FileOffset += FileOccupiedSize;
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
break;
case EFI_FILE_DELETED:
FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
FileOffset += FileOccupiedSize;
FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
break;
default:
*FileHeader = NULL;
return EFI_NOT_FOUND;
}
}
*FileHeader = NULL;
return EFI_NOT_FOUND;
}
/**
Go through the file to search SectionType section,
when meeting an encapsuled section.
@param SectionType - Filter to find only section of this type.
@param Section - From where to search.
@param SectionSize - The file size to search.
@param OutputBuffer - Pointer to the section to search.
@retval EFI_SUCCESS
**/
EFI_STATUS
FfsProcessSection (
IN EFI_SECTION_TYPE SectionType,
IN EFI_COMMON_SECTION_HEADER *Section,
IN UINTN SectionSize,
OUT VOID **OutputBuffer
)
{
EFI_STATUS Status;
UINT32 SectionLength;
UINT32 ParsedLength;
EFI_COMPRESSION_SECTION *CompressionSection;
UINTN DstBufferSize;
VOID *ScratchBuffer;
UINT32 ScratchBufferSize;
VOID *DstBuffer;
UINT16 SectionAttribute;
UINT32 AuthenticationStatus;
*OutputBuffer = NULL;
ParsedLength = 0;
Status = EFI_NOT_FOUND;
while (ParsedLength < SectionSize) {
if (Section->Type == SectionType) {
*OutputBuffer = (VOID *)(Section + 1);
return EFI_SUCCESS;
} else if ((Section->Type == EFI_SECTION_COMPRESSION) || (Section->Type == EFI_SECTION_GUID_DEFINED)) {
if (Section->Type == EFI_SECTION_COMPRESSION) {
CompressionSection = (EFI_COMPRESSION_SECTION *) Section;
SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
if (CompressionSection->CompressionType != EFI_STANDARD_COMPRESSION) {
return EFI_UNSUPPORTED;
}
Status = UefiDecompressGetInfo (
(UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
(UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
(UINT32 *) &DstBufferSize,
&ScratchBufferSize
);
} else if (Section->Type == EFI_SECTION_GUID_DEFINED) {
Status = ExtractGuidedSectionGetInfo (
Section,
(UINT32 *) &DstBufferSize,
&ScratchBufferSize,
&SectionAttribute
);
}
if (EFI_ERROR (Status)) {
//
// GetInfo failed
//
DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));
return EFI_NOT_FOUND;
}
//
// Allocate scratch buffer
//
ScratchBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
if (ScratchBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Allocate destination buffer, extra one page for adjustment
//
DstBuffer = (VOID *)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
if (DstBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
// to make section data at page alignment.
//
DstBuffer = (UINT8 *)DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
//
// Call decompress function
//
if (Section->Type == EFI_SECTION_COMPRESSION) {
Status = UefiDecompress (
(CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
DstBuffer,
ScratchBuffer
);
} else if (Section->Type == EFI_SECTION_GUID_DEFINED) {
Status = ExtractGuidedSectionDecode (
Section,
&DstBuffer,
ScratchBuffer,
&AuthenticationStatus
);
}
if (EFI_ERROR (Status)) {
//
// Decompress failed
//
DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));
return EFI_NOT_FOUND;
} else {
return FfsProcessSection (
SectionType,
DstBuffer,
DstBufferSize,
OutputBuffer
);
}
}
//
// Size is 24 bits wide so mask upper 8 bits.
// SectionLength is adjusted it is 4 byte aligned.
// Go to the next section
//
SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
ASSERT (SectionLength != 0);
ParsedLength += SectionLength;
Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
}
return EFI_NOT_FOUND;
}
/**
This service enables discovery sections of a given type within a valid FFS file.
@param SearchType The value of the section type to find.
@param FfsFileHeader A pointer to the file header that contains the set of sections to
be searched.
@param SectionData A pointer to the discovered section, if successful.
@retval EFI_SUCCESS The section was found.
@retval EFI_NOT_FOUND The section was not found.
**/
EFI_STATUS
EFIAPI
FfsFindSectionData (
IN EFI_SECTION_TYPE SectionType,
IN EFI_PEI_FILE_HANDLE FileHandle,
OUT VOID **SectionData
)
{
EFI_FFS_FILE_HEADER *FfsFileHeader;
UINT32 FileSize;
EFI_COMMON_SECTION_HEADER *Section;
FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);
//
// Size is 24 bits wide so mask upper 8 bits.
// Does not include FfsFileHeader header size
// FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
//
Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);
FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
FileSize -= sizeof (EFI_FFS_FILE_HEADER);
return FfsProcessSection (
SectionType,
Section,
FileSize,
SectionData
);
}
/**
This service enables discovery of additional firmware files.
@param SearchType A filter to find files only of this type.
@param FwVolHeader Pointer to the firmware volume header of the volume to search.
This parameter must point to a valid FFS volume.
@param FileHeader Pointer to the current file from which to begin searching.
@retval EFI_SUCCESS The file was found.
@retval EFI_NOT_FOUND The file was not found.
@retval EFI_NOT_FOUND The header checksum was not zero.
**/
EFI_STATUS
EFIAPI
FfsFindNextFile (
IN UINT8 SearchType,
IN EFI_PEI_FV_HANDLE VolumeHandle,
IN OUT EFI_PEI_FILE_HANDLE *FileHandle
)
{
return FindFileEx (VolumeHandle, NULL, SearchType, FileHandle);
}
/**
This service enables discovery of additional firmware volumes.
@param Instance This instance of the firmware volume to find. The value 0 is the
Boot Firmware Volume (BFV).
@param FwVolHeader Pointer to the firmware volume header of the volume to return.
@retval EFI_SUCCESS The volume was found.
@retval EFI_NOT_FOUND The volume was not found.
**/
EFI_STATUS
EFIAPI
FfsFindNextVolume (
IN UINTN Instance,
IN OUT EFI_PEI_FV_HANDLE *VolumeHandle
)
{
EFI_PEI_HOB_POINTERS Hob;
Hob.Raw = GetHobList ();
if (Hob.Raw == NULL) {
return EFI_NOT_FOUND;
}
do {
Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw);
if (Hob.Raw != NULL) {
if (Instance-- == 0) {
*VolumeHandle = (EFI_PEI_FV_HANDLE)(UINTN)(Hob.FirmwareVolume->BaseAddress);
return EFI_SUCCESS;
}
Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, GET_NEXT_HOB (Hob));
}
} while (Hob.Raw != NULL);
return EFI_NOT_FOUND;
}
/**
Find a file in the volume by name
@param FileName A pointer to the name of the file to
find within the firmware volume.
@param VolumeHandle The firmware volume to search FileHandle
Upon exit, points to the found file's
handle or NULL if it could not be found.
@retval EFI_SUCCESS File was found.
@retval EFI_NOT_FOUND File was not found.
@retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or
FileName was NULL.
**/
EFI_STATUS
EFIAPI
FfsFindFileByName (
IN CONST EFI_GUID *FileName,
IN EFI_PEI_FV_HANDLE VolumeHandle,
OUT EFI_PEI_FILE_HANDLE *FileHandle
)
{
EFI_STATUS Status;
if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
Status = FindFileEx (VolumeHandle, FileName, 0, FileHandle);
if (Status == EFI_NOT_FOUND) {
*FileHandle = NULL;
}
return Status;
}
/**
Get information about the file by name.
@param FileHandle Handle of the file.
@param FileInfo Upon exit, points to the file's
information.
@retval EFI_SUCCESS File information returned.
@retval EFI_INVALID_PARAMETER If FileHandle does not
represent a valid file.
@retval EFI_INVALID_PARAMETER If FileInfo is NULL.
**/
EFI_STATUS
EFIAPI
FfsGetFileInfo (
IN EFI_PEI_FILE_HANDLE FileHandle,
OUT EFI_FV_FILE_INFO *FileInfo
)
{
UINT8 FileState;
UINT8 ErasePolarity;
EFI_FFS_FILE_HEADER *FileHeader;
EFI_PEI_FV_HANDLE VolumeHandle;
if ((FileHandle == NULL) || (FileInfo == NULL)) {
return EFI_INVALID_PARAMETER;
}
VolumeHandle = 0;
//
// Retrieve the FirmwareVolume which the file resides in.
//
if (!FileHandleToVolume(FileHandle, &VolumeHandle)) {
return EFI_INVALID_PARAMETER;
}
if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB2_ERASE_POLARITY) {
ErasePolarity = 1;
} else {
ErasePolarity = 0;
}
//
// Get FileState which is the highest bit of the State
//
FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);
switch (FileState) {
case EFI_FILE_DATA_VALID:
case EFI_FILE_MARKED_FOR_UPDATE:
break;
default:
return EFI_INVALID_PARAMETER;
}
FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));
FileInfo->FileType = FileHeader->Type;
FileInfo->FileAttributes = FileHeader->Attributes;
FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER);
FileInfo->Buffer = (FileHeader + 1);
return EFI_SUCCESS;
}
/**
Get Information about the volume by name
@param VolumeHandle Handle of the volume.
@param VolumeInfo Upon exit, points to the volume's
information.
@retval EFI_SUCCESS File information returned.
@retval EFI_INVALID_PARAMETER If FileHandle does not
represent a valid file.
@retval EFI_INVALID_PARAMETER If FileInfo is NULL.
**/
EFI_STATUS
EFIAPI
FfsGetVolumeInfo (
IN EFI_PEI_FV_HANDLE VolumeHandle,
OUT EFI_FV_INFO *VolumeInfo
)
{
EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;
EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;
if (VolumeInfo == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// VolumeHandle may not align at 8 byte,
// but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
// So, Copy FvHeader into the local FvHeader structure.
//
CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
//
// Check Fv Image Signature
//
if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {
return EFI_INVALID_PARAMETER;
}
VolumeInfo->FvAttributes = FwVolHeader.Attributes;
VolumeInfo->FvStart = (VOID *) VolumeHandle;
VolumeInfo->FvSize = FwVolHeader.FvLength;
CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));
if (FwVolHeader.ExtHeaderOffset != 0) {
FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + FwVolHeader.ExtHeaderOffset);
CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));
}
return EFI_SUCCESS;
}
/**
Search through every FV until you find a file of type FileType
@param FileType File handle of a Fv type file.
@param Volumehandle On succes Volume Handle of the match
@param FileHandle On success File Handle of the match
@retval EFI_NOT_FOUND FV image can't be found.
@retval EFI_SUCCESS Successfully found FileType
**/
EFI_STATUS
EFIAPI
FfsAnyFvFindFirstFile (
IN EFI_FV_FILETYPE FileType,
OUT EFI_PEI_FV_HANDLE *VolumeHandle,
OUT EFI_PEI_FILE_HANDLE *FileHandle
)
{
EFI_STATUS Status;
UINTN Instance;
//
// Search every FV for the DXE Core
//
Instance = 0;
*FileHandle = NULL;
while (1)
{
Status = FfsFindNextVolume (Instance++, VolumeHandle);
if (EFI_ERROR (Status))
{
break;
}
Status = FfsFindNextFile (FileType, *VolumeHandle, FileHandle);
if (!EFI_ERROR (Status))
{
break;
}
}
return Status;
}
/**
Get Fv image from the FV type file, then add FV & FV2 Hob.
@param FileHandle File handle of a Fv type file.
@retval EFI_NOT_FOUND FV image can't be found.
@retval EFI_SUCCESS Successfully to process it.
**/
EFI_STATUS
EFIAPI
FfsProcessFvFile (
IN EFI_PEI_FILE_HANDLE FvFileHandle
)
{
EFI_STATUS Status;
EFI_PEI_FV_HANDLE FvImageHandle;
EFI_FV_INFO FvImageInfo;
UINT32 FvAlignment;
VOID *FvBuffer;
EFI_PEI_HOB_POINTERS HobFv2;
FvBuffer = NULL;
//
// Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
// been extracted.
//
HobFv2.Raw = GetHobList ();
while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {
if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name), &HobFv2.FirmwareVolume2->FileName)) {
//
// this FILE has been dispatched, it will not be dispatched again.
//
return EFI_SUCCESS;
}
HobFv2.Raw = GET_NEXT_HOB (HobFv2);
}
//
// Find FvImage in FvFile
//
Status = FfsFindSectionData (EFI_SECTION_FIRMWARE_VOLUME_IMAGE, FvFileHandle, (VOID **)&FvImageHandle);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Collect FvImage Info.
//
Status = FfsGetVolumeInfo (FvImageHandle, &FvImageInfo);
ASSERT_EFI_ERROR (Status);
//
// FvAlignment must be more than 8 bytes required by FvHeader structure.
//
FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16);
if (FvAlignment < 8) {
FvAlignment = 8;
}
//
// Check FvImage
//
if ((UINTN) FvImageInfo.FvStart % FvAlignment != 0) {
FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvImageInfo.FvSize), FvAlignment);
if (FvBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN) FvImageInfo.FvSize);
//
// Update FvImageInfo after reload FvImage to new aligned memory
//
FfsGetVolumeInfo ((EFI_PEI_FV_HANDLE) FvBuffer, &FvImageInfo);
}
//
// Inform HOB consumer phase, i.e. DXE core, the existance of this FV
//
BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart, FvImageInfo.FvSize);
//
// Makes the encapsulated volume show up in DXE phase to skip processing of
// encapsulated file again.
//
BuildFv2Hob (
(EFI_PHYSICAL_ADDRESS) (UINTN) FvImageInfo.FvStart,
FvImageInfo.FvSize,
&FvImageInfo.FvName,
&(((EFI_FFS_FILE_HEADER *)FvFileHandle)->Name)
);
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,808 @@
/** @file
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 <PrePi.h>
#include <Guid/MemoryTypeInformation.h>
//
// Have to use build system to set the original value in case we are running
// from FLASH and globals don't work. So if you do a GetHobList() and gHobList
// and gHobList is NULL the PCD default values are used.
//
VOID *gHobList = NULL;
// May want to put this into a library so you only need the PCD setings if you are using the feature?
VOID
BuildMemoryTypeInformationHob (
VOID
)
{
EFI_MEMORY_TYPE_INFORMATION Info[10];
Info[0].Type = EfiACPIReclaimMemory;
Info[0].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory);
Info[1].Type = EfiACPIMemoryNVS;
Info[1].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS);
Info[2].Type = EfiReservedMemoryType;
Info[2].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiReservedMemoryType);
Info[3].Type = EfiRuntimeServicesData;
Info[3].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesData);
Info[4].Type = EfiRuntimeServicesCode;
Info[4].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode);
Info[5].Type = EfiBootServicesCode;
Info[5].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesCode);
Info[6].Type = EfiBootServicesData;
Info[6].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiBootServicesData);
Info[7].Type = EfiLoaderCode;
Info[7].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderCode);
Info[8].Type = EfiLoaderData;
Info[8].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiLoaderData);
// Terminator for the list
Info[9].Type = EfiMaxMemoryType;
Info[9].NumberOfPages = 0;
BuildGuidDataHob (&gEfiMemoryTypeInformationGuid, &Info, sizeof (Info));
}
/**
**/
VOID
CreateHobList (
IN VOID *MemoryBegin,
IN UINTN MemoryLength,
IN VOID *HobBase,
IN VOID *StackBase
)
{
EFI_HOB_HANDOFF_INFO_TABLE *Hob;
EFI_HOB_GENERIC_HEADER *HobEnd;
EFI_RESOURCE_ATTRIBUTE_TYPE Attributes;
Hob = HobBase;
HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1);
Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF;
Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE);
Hob->Header.Reserved = 0;
HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
HobEnd->Reserved = 0;
Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION;
Hob->BootMode = BOOT_WITH_FULL_CONFIGURATION;
Hob->EfiMemoryTop = (UINTN)MemoryBegin + MemoryLength;
Hob->EfiMemoryBottom = (UINTN)MemoryBegin;
Hob->EfiFreeMemoryTop = (UINTN)StackBase;
Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd+1);
Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;
SetHobList (Hob);
BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
Attributes =(
EFI_RESOURCE_ATTRIBUTE_PRESENT |
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
EFI_RESOURCE_ATTRIBUTE_TESTED |
EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
);
BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, Attributes, (UINTN)MemoryBegin, MemoryLength);
BuildStackHob ((UINTN)StackBase, Hob->EfiMemoryTop - (UINTN)StackBase);
if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
// Optional feature that helps prevent EFI memory map fragmentation.
BuildMemoryTypeInformationHob ();
}
}
VOID
EFIAPI
BuildFvHobs (
IN EFI_PHYSICAL_ADDRESS PhysicalStart,
IN UINT64 NumberOfBytes,
IN EFI_RESOURCE_ATTRIBUTE_TYPE *ResourceAttribute
)
{
EFI_RESOURCE_ATTRIBUTE_TYPE Resource;
BuildFvHob (PhysicalStart, NumberOfBytes);
if (ResourceAttribute == NULL) {
Resource = (EFI_RESOURCE_ATTRIBUTE_PRESENT |
EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
EFI_RESOURCE_ATTRIBUTE_TESTED |
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE);
} else {
Resource = *ResourceAttribute;
}
BuildResourceDescriptorHob (EFI_RESOURCE_FIRMWARE_DEVICE, Resource, PhysicalStart, NumberOfBytes);
}
/**
Returns the pointer to the HOB list.
This function returns the pointer to first HOB in the list.
@return The pointer to the HOB list.
**/
VOID *
EFIAPI
GetHobList (
VOID
)
{
if (gHobList == NULL) {
return (VOID *)(UINTN)PcdGet32 (PcdPrePiHobBase);
} else {
return gHobList;
}
}
/**
Updates the pointer to the HOB list.
@param HobList Hob list pointer to store
**/
EFI_STATUS
EFIAPI
SetHobList (
IN VOID *HobList
)
{
gHobList = HobList;
//
// If this code is running from ROM this could fail
//
return (gHobList == HobList) ? EFI_SUCCESS: EFI_UNSUPPORTED;
}
VOID *
CreateHob (
IN UINT16 HobType,
IN UINT16 HobLength
)
{
EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
EFI_HOB_GENERIC_HEADER *HobEnd;
EFI_PHYSICAL_ADDRESS FreeMemory;
VOID *Hob;
HandOffHob = GetHobList ();
HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;
if (FreeMemory < HobLength) {
return NULL;
}
Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType;
((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength;
((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0;
HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength);
HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
HobEnd->Reserved = 0;
HobEnd++;
HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
return Hob;
}
/**
Returns the next instance of a HOB type from the starting HOB.
This function searches the first instance of a HOB type from the starting HOB pointer.
If there does not exist such HOB type from the starting HOB pointer, it will return NULL.
In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
unconditionally: it returns HobStart back if HobStart itself meets the requirement;
caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
If HobStart is NULL, then ASSERT().
@param Type The HOB type to return.
@param HobStart The starting HOB pointer to search from.
@return The next instance of a HOB type from the starting HOB.
**/
VOID *
EFIAPI
GetNextHob (
IN UINT16 Type,
IN CONST VOID *HobStart
)
{
EFI_PEI_HOB_POINTERS Hob;
ASSERT (HobStart != NULL);
Hob.Raw = (UINT8 *) HobStart;
//
// Parse the HOB list until end of list or matching type is found.
//
while (!END_OF_HOB_LIST (Hob)) {
if (Hob.Header->HobType == Type) {
return Hob.Raw;
}
Hob.Raw = GET_NEXT_HOB (Hob);
}
return NULL;
}
/**
Returns the first instance of a HOB type among the whole HOB list.
This function searches the first instance of a HOB type among the whole HOB list.
If there does not exist such HOB type in the HOB list, it will return NULL.
@param Type The HOB type to return.
@return The next instance of a HOB type from the starting HOB.
**/
VOID *
EFIAPI
GetFirstHob (
IN UINT16 Type
)
{
VOID *HobList;
HobList = GetHobList ();
return GetNextHob (Type, HobList);
}
/**
This function searches the first instance of a HOB from the starting HOB pointer.
Such HOB should satisfy two conditions:
its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
If there does not exist such HOB from the starting HOB pointer, it will return NULL.
Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
to extract the data section and its size info respectively.
In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
unconditionally: it returns HobStart back if HobStart itself meets the requirement;
caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
If Guid is NULL, then ASSERT().
If HobStart is NULL, then ASSERT().
@param Guid The GUID to match with in the HOB list.
@param HobStart A pointer to a Guid.
@return The next instance of the matched GUID HOB from the starting HOB.
**/
VOID *
EFIAPI
GetNextGuidHob (
IN CONST EFI_GUID *Guid,
IN CONST VOID *HobStart
){
EFI_PEI_HOB_POINTERS GuidHob;
GuidHob.Raw = (UINT8 *) HobStart;
while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) {
if (CompareGuid (Guid, &GuidHob.Guid->Name)) {
break;
}
GuidHob.Raw = GET_NEXT_HOB (GuidHob);
}
return GuidHob.Raw;
}
/**
This function searches the first instance of a HOB among the whole HOB list.
Such HOB should satisfy two conditions:
its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
If there does not exist such HOB from the starting HOB pointer, it will return NULL.
Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
to extract the data section and its size info respectively.
If Guid is NULL, then ASSERT().
@param Guid The GUID to match with in the HOB list.
@return The first instance of the matched GUID HOB among the whole HOB list.
**/
VOID *
EFIAPI
GetFirstGuidHob (
IN CONST EFI_GUID *Guid
)
{
VOID *HobList;
HobList = GetHobList ();
return GetNextGuidHob (Guid, HobList);
}
/**
Get the Boot Mode from the HOB list.
This function returns the system boot mode information from the
PHIT HOB in HOB list.
@param VOID
@return The Boot Mode.
**/
EFI_BOOT_MODE
EFIAPI
GetBootMode (
VOID
)
{
EFI_PEI_HOB_POINTERS Hob;
Hob.Raw = GetHobList ();
return Hob.HandoffInformationTable->BootMode;
}
/**
Get the Boot Mode from the HOB list.
This function returns the system boot mode information from the
PHIT HOB in HOB list.
@param VOID
@return The Boot Mode.
**/
EFI_STATUS
EFIAPI
SetBootMode (
IN EFI_BOOT_MODE BootMode
)
{
EFI_PEI_HOB_POINTERS Hob;
Hob.Raw = GetHobList ();
Hob.HandoffInformationTable->BootMode = BootMode;
return BootMode;
}
/**
Builds a HOB for a loaded PE32 module.
This function builds a HOB for a loaded PE32 module.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If ModuleName is NULL, then ASSERT().
If there is no additional space for HOB creation, then ASSERT().
@param ModuleName The GUID File Name of the module.
@param MemoryAllocationModule The 64 bit physical address of the module.
@param ModuleLength The length of the module in bytes.
@param EntryPoint The 64 bit physical address of the module entry point.
**/
VOID
EFIAPI
BuildModuleHob (
IN CONST EFI_GUID *ModuleName,
IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule,
IN UINT64 ModuleLength,
IN EFI_PHYSICAL_ADDRESS EntryPoint
)
{
EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob;
ASSERT (((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) &&
((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0));
Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE));
CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid);
Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule;
Hob->MemoryAllocationHeader.MemoryLength = ModuleLength;
Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode;
//
// Zero the reserved space to match HOB spec
//
ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved));
CopyGuid (&Hob->ModuleName, ModuleName);
Hob->EntryPoint = EntryPoint;
}
/**
Builds a HOB that describes a chunk of system memory.
This function builds a HOB that describes a chunk of system memory.
If there is no additional space for HOB creation, then ASSERT().
@param ResourceType The type of resource described by this HOB.
@param ResourceAttribute The resource attributes of the memory described by this HOB.
@param PhysicalStart The 64 bit physical address of memory described by this HOB.
@param NumberOfBytes The length of the memory described by this HOB in bytes.
**/
VOID
EFIAPI
BuildResourceDescriptorHob (
IN EFI_RESOURCE_TYPE ResourceType,
IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
IN EFI_PHYSICAL_ADDRESS PhysicalStart,
IN UINT64 NumberOfBytes
)
{
EFI_HOB_RESOURCE_DESCRIPTOR *Hob;
Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
Hob->ResourceType = ResourceType;
Hob->ResourceAttribute = ResourceAttribute;
Hob->PhysicalStart = PhysicalStart;
Hob->ResourceLength = NumberOfBytes;
}
/**
Builds a GUID HOB with a certain data length.
This function builds a customized HOB tagged with a GUID for identification
and returns the start address of GUID HOB data so that caller can fill the customized data.
The HOB Header and Name field is already stripped.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If Guid is NULL, then ASSERT().
If there is no additional space for HOB creation, then ASSERT().
If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
@param Guid The GUID to tag the customized HOB.
@param DataLength The size of the data payload for the GUID HOB.
@return The start address of GUID HOB data.
**/
VOID *
EFIAPI
BuildGuidHob (
IN CONST EFI_GUID *Guid,
IN UINTN DataLength
)
{
EFI_HOB_GUID_TYPE *Hob;
//
// Make sure that data length is not too long.
//
ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE)));
Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength));
CopyGuid (&Hob->Name, Guid);
return Hob + 1;
}
/**
Copies a data buffer to a newly-built HOB.
This function builds a customized HOB tagged with a GUID for identification,
copies the input data to the HOB data field and returns the start address of the GUID HOB data.
The HOB Header and Name field is already stripped.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If Guid is NULL, then ASSERT().
If Data is NULL and DataLength > 0, then ASSERT().
If there is no additional space for HOB creation, then ASSERT().
If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
@param Guid The GUID to tag the customized HOB.
@param Data The data to be copied into the data field of the GUID HOB.
@param DataLength The size of the data payload for the GUID HOB.
@return The start address of GUID HOB data.
**/
VOID *
EFIAPI
BuildGuidDataHob (
IN CONST EFI_GUID *Guid,
IN VOID *Data,
IN UINTN DataLength
)
{
VOID *HobData;
ASSERT (Data != NULL || DataLength == 0);
HobData = BuildGuidHob (Guid, DataLength);
return CopyMem (HobData, Data, DataLength);
}
/**
Builds a Firmware Volume HOB.
This function builds a Firmware Volume HOB.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The base address of the Firmware Volume.
@param Length The size of the Firmware Volume in bytes.
**/
VOID
EFIAPI
BuildFvHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
)
{
EFI_HOB_FIRMWARE_VOLUME *Hob;
Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME));
Hob->BaseAddress = BaseAddress;
Hob->Length = Length;
}
/**
Builds a EFI_HOB_TYPE_FV2 HOB.
This function builds a EFI_HOB_TYPE_FV2 HOB.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The base address of the Firmware Volume.
@param Length The size of the Firmware Volume in bytes.
@param FvName The name of the Firmware Volume.
@param FileName The name of the file.
**/
VOID
EFIAPI
BuildFv2Hob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN CONST EFI_GUID *FvName,
IN CONST EFI_GUID *FileName
)
{
EFI_HOB_FIRMWARE_VOLUME2 *Hob;
Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2));
Hob->BaseAddress = BaseAddress;
Hob->Length = Length;
CopyGuid (&Hob->FvName, FvName);
CopyGuid (&Hob->FileName, FileName);
}
/**
Builds a Capsule Volume HOB.
This function builds a Capsule Volume HOB.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The base address of the Capsule Volume.
@param Length The size of the Capsule Volume in bytes.
**/
VOID
EFIAPI
BuildCvHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
)
{
ASSERT (FALSE);
}
/**
Builds a HOB for the CPU.
This function builds a HOB for the CPU.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param SizeOfMemorySpace The maximum physical memory addressability of the processor.
@param SizeOfIoSpace The maximum physical I/O addressability of the processor.
**/
VOID
EFIAPI
BuildCpuHob (
IN UINT8 SizeOfMemorySpace,
IN UINT8 SizeOfIoSpace
)
{
EFI_HOB_CPU *Hob;
Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU));
Hob->SizeOfMemorySpace = SizeOfMemorySpace;
Hob->SizeOfIoSpace = SizeOfIoSpace;
//
// Zero the reserved space to match HOB spec
//
ZeroMem (Hob->Reserved, sizeof (Hob->Reserved));
}
/**
Builds a HOB for the Stack.
This function builds a HOB for the stack.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The 64 bit physical address of the Stack.
@param Length The length of the stack in bytes.
**/
VOID
EFIAPI
BuildStackHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
)
{
EFI_HOB_MEMORY_ALLOCATION_STACK *Hob;
ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) &&
((Length & (EFI_PAGE_SIZE - 1)) == 0));
Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK));
CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid);
Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
Hob->AllocDescriptor.MemoryLength = Length;
Hob->AllocDescriptor.MemoryType = EfiBootServicesData;
//
// Zero the reserved space to match HOB spec
//
ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved));
}
/**
Update the Stack Hob if the stack has been moved
@param BaseAddress The 64 bit physical address of the Stack.
@param Length The length of the stack in bytes.
**/
VOID
UpdateStackHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
)
{
EFI_PEI_HOB_POINTERS Hob;
Hob.Raw = GetHobList ();
while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {
//
// Build a new memory allocation HOB with old stack info with EfiConventionalMemory type
// to be reclaimed by DXE core.
//
BuildMemoryAllocationHob (
Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,
Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,
EfiConventionalMemory
);
//
// Update the BSP Stack Hob to reflect the new stack info.
//
Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;
Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;
break;
}
Hob.Raw = GET_NEXT_HOB (Hob);
}
}
/**
Builds a HOB for the memory allocation.
This function builds a HOB for the memory allocation.
It can only be invoked during PEI phase;
for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The 64 bit physical address of the memory.
@param Length The length of the memory allocation in bytes.
@param MemoryType Type of memory allocated by this HOB.
**/
VOID
EFIAPI
BuildMemoryAllocationHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN EFI_MEMORY_TYPE MemoryType
)
{
EFI_HOB_MEMORY_ALLOCATION *Hob;
ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) &&
((Length & (EFI_PAGE_SIZE - 1)) == 0));
Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION));
ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID));
Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
Hob->AllocDescriptor.MemoryLength = Length;
Hob->AllocDescriptor.MemoryType = MemoryType;
//
// Zero the reserved space to match HOB spec
//
ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved));
}

View File

@@ -0,0 +1,160 @@
/** @file
Implementation of the 6 PEI Ffs (FV) APIs in library form.
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 <PrePi.h>
/**
Allocates one or more 4KB pages of type EfiBootServicesData.
Allocates the number of 4KB pages of MemoryType and returns a pointer to the
allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
is returned. If there is not enough memory remaining to satisfy the request, then NULL is
returned.
@param Pages The number of 4 KB pages to allocate.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocatePages (
IN UINTN Pages
)
{
EFI_PEI_HOB_POINTERS Hob;
EFI_PHYSICAL_ADDRESS Offset;
Hob.Raw = GetHobList ();
// Check to see if on 4k boundary
Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF;
if (Offset != 0) {
// If not aligned, make the allocation aligned.
Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset;
}
//
// Verify that there is sufficient memory to satisfy the allocation
//
if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < Hob.HandoffInformationTable->EfiFreeMemoryBottom) {
return 0;
} else {
//
// Update the PHIT to reflect the memory usage
//
Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE;
// This routine used to create a memory allocation HOB a la PEI, but that's not
// necessary for us.
return (VOID *)(UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop;
}
}
/**
Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is
returned. If there is not enough memory at the specified alignment remaining to satisfy the
request, then NULL is returned.
If Alignment is not a power of two and Alignment is not zero, then ASSERT().
@param Pages The number of 4 KB pages to allocate.
@param Alignment The requested alignment of the allocation. Must be a power of two.
If Alignment is zero, then byte alignment is used.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocateAlignedPages (
IN UINTN Pages,
IN UINTN Alignment
)
{
VOID *Memory;
UINTN AlignmentMask;
//
// Alignment must be a power of two or zero.
//
ASSERT ((Alignment & (Alignment - 1)) == 0);
if (Pages == 0) {
return NULL;
}
//
// Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
//
ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
//
// We would rather waste some memory to save PEI code size.
//
Memory = (VOID *)(UINTN)AllocatePages (Pages + EFI_SIZE_TO_PAGES (Alignment));
if (Alignment == 0) {
AlignmentMask = Alignment;
} else {
AlignmentMask = Alignment - 1;
}
return (VOID *) (UINTN) (((UINTN) Memory + AlignmentMask) & ~AlignmentMask);
}
/**
Allocates a buffer of type EfiBootServicesData.
Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is
returned. If there is not enough memory remaining to satisfy the request, then NULL is returned.
@param AllocationSize The number of bytes to allocate.
@return A pointer to the allocated buffer or NULL if allocation fails.
**/
VOID *
EFIAPI
AllocatePool (
IN UINTN AllocationSize
)
{
EFI_HOB_MEMORY_POOL *Hob;
Hob = GetHobList ();
//
// Verify that there is sufficient memory to satisfy the allocation
//
if (AllocationSize > 0x10000) {
// Please call AllcoatePages for big allocations
return 0;
} else {
Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL, (UINT16)(sizeof (EFI_HOB_TYPE_MEMORY_POOL) + AllocationSize));
return (VOID *)(Hob + 1);
}
}

View File

@@ -0,0 +1,44 @@
/** @file
Library that helps implement monolithic PEI (i.e. PEI part of SEC)
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 _PI_PEI_H_
#define _PI_PEI_H_
#include <PiPei.h>
#include <Library/BaseLib.h>
#include <Library/PrePiLib.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiDecompressLib.h>
#include <Library/PeCoffLib.h>
#include <Library/CacheMaintenanceLib.h>
#include <Guid/MemoryAllocationHob.h>
#define GET_HOB_TYPE(Hob) ((Hob).Header->HobType)
#define GET_HOB_LENGTH(Hob) ((Hob).Header->HobLength)
#define GET_NEXT_HOB(Hob) ((Hob).Raw + GET_HOB_LENGTH (Hob))
#define END_OF_HOB_LIST(Hob) (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_END_OF_HOB_LIST)
//
// Get the data and data size field of GUID
//
#define GET_GUID_HOB_DATA(GuidHob) ((VOID *) (((UINT8 *) &((GuidHob)->Name)) + sizeof (EFI_GUID)))
#define GET_GUID_HOB_DATA_SIZE(GuidHob) (((GuidHob)->Header).HobLength - sizeof (EFI_HOB_GUID_TYPE))
#endif

View File

@@ -0,0 +1,231 @@
/** @file
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 <PrePi.h>
//
// Hack to work in NT32
//
EFI_STATUS
EFIAPI
SecWinNtPeiLoadFile (
IN VOID *Pe32Data,
IN EFI_PHYSICAL_ADDRESS *ImageAddress,
IN UINT64 *ImageSize,
IN EFI_PHYSICAL_ADDRESS *EntryPoint
);
EFI_STATUS
EFIAPI
LoadPeCoffImage (
IN VOID *PeCoffImage,
OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
OUT UINT64 *ImageSize,
OUT EFI_PHYSICAL_ADDRESS *EntryPoint
)
{
RETURN_STATUS Status;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
VOID *Buffer;
ZeroMem (&ImageContext, sizeof (ImageContext));
ImageContext.Handle = PeCoffImage;
ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
Status = PeCoffLoaderGetImageInfo (&ImageContext);
ASSERT_EFI_ERROR (Status);
//
// Allocate Memory for the image
//
Buffer = AllocatePages (EFI_SIZE_TO_PAGES((UINT32)ImageContext.ImageSize));
ASSERT (Buffer != 0);
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
//
// Load the image to our new buffer
//
Status = PeCoffLoaderLoadImage (&ImageContext);
ASSERT_EFI_ERROR (Status);
//
// Relocate the image in our new buffer
//
Status = PeCoffLoaderRelocateImage (&ImageContext);
ASSERT_EFI_ERROR (Status);
*ImageAddress = ImageContext.ImageAddress;
*ImageSize = ImageContext.ImageSize;
*EntryPoint = ImageContext.EntryPoint;
//
// Flush not needed for all architectures. We could have a processor specific
// function in this library that does the no-op if needed.
//
InvalidateInstructionCacheRange ((VOID *)(UINTN)*ImageAddress, (UINTN)*ImageSize);
return Status;
}
typedef
VOID
(EFIAPI *DXE_CORE_ENTRY_POINT) (
IN VOID *HobStart
);
EFI_STATUS
EFIAPI
LoadDxeCoreFromFfsFile (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN UINTN StackSize
)
{
EFI_STATUS Status;
VOID *PeCoffImage;
EFI_PHYSICAL_ADDRESS ImageAddress;
UINT64 ImageSize;
EFI_PHYSICAL_ADDRESS EntryPoint;
VOID *BaseOfStack;
VOID *TopOfStack;
VOID *Hob;
EFI_FV_FILE_INFO FvFileInfo;
Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage);
if (EFI_ERROR (Status)) {
return Status;
}
Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
// For NT32 Debug Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
ASSERT_EFI_ERROR (Status);
//
// Extract the DxeCore GUID file name.
//
Status = FfsGetFileInfo (FileHandle, &FvFileInfo);
ASSERT_EFI_ERROR (Status);
BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, EntryPoint);
DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint));
Hob = GetHobList ();
if (StackSize == 0) {
// User the current stack
((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint) (Hob);
} else {
//
// Allocate 128KB for the Stack
//
BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize));
ASSERT (BaseOfStack != NULL);
//
// Compute the top of the stack we were allocated. Pre-allocate a UINTN
// for safety.
//
TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
//
// Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
//
UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, StackSize);
SwitchStack (
(SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint,
Hob,
NULL,
TopOfStack
);
}
// Should never get here as DXE Core does not return
DEBUG ((EFI_D_ERROR, "DxeCore returned\n"));
ASSERT (FALSE);
return EFI_DEVICE_ERROR;
}
EFI_STATUS
EFIAPI
LoadDxeCoreFromFv (
IN UINTN *FvInstance, OPTIONAL
IN UINTN StackSize
)
{
EFI_STATUS Status;
EFI_PEI_FV_HANDLE VolumeHandle;
EFI_PEI_FILE_HANDLE FileHandle = NULL;
if (FvInstance != NULL) {
//
// Caller passed in a specific FV to try, so only try that one
//
Status = FfsFindNextVolume (*FvInstance, &VolumeHandle);
if (!EFI_ERROR (Status)) {
Status = FfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
}
} else {
Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle);
}
if (!EFI_ERROR (Status)) {
return LoadDxeCoreFromFfsFile (FileHandle, StackSize);
}
return Status;
}
EFI_STATUS
EFIAPI
DecompressFirstFv (
VOID
)
{
EFI_STATUS Status;
EFI_PEI_FV_HANDLE VolumeHandle;
EFI_PEI_FILE_HANDLE FileHandle;
Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &VolumeHandle, &FileHandle);
if (!EFI_ERROR (Status)) {
Status = FfsProcessFvFile (FileHandle);
}
return Status;
}

View File

@@ -0,0 +1,90 @@
#%HEADER%
#/** @file
# Component description file for Apple Pre PI Library
#
# LIbrary helps you build a platform that skips PEI and loads DXE Core
# directly. Helps building HOBs, reading data from the FV, and doing
# decompression.
#
# Copyright (c) 2008, Apple, Inc.
#
# 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]
INF_VERSION = 0x00010005
BASE_NAME = PrePiLib
FILE_GUID = 1F3A3278-82EB-4C0D-86F1-5BCDA5846CB2
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = PrePiLib
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
FwVol.c
Hob.c
Memory.c
PrePiLib.c
ReportStatusCode.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec # needed to support StatusCodes
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec # needed to support StatusCodes
[LibraryClasses]
BaseLib
DebugLib
BaseMemoryLib
UefiDecompressLib
PeCoffLib
CacheMaintenanceLib
PrintLib
SerialPortLib
ExtractGuidedSectionLib
[Guids]
gEfiHobMemoryAllocModuleGuid
gEfiHobMemoryAllocStackGuid
gEfiStatusCodeSpecificDataGuid
gEfiMemoryTypeInformationGuid
gEfiStatusCodeDataTypeDebugGuid
[Protocols]
gEfiStatusCodeRuntimeProtocolGuid
[FixedPcd.common]
gEmbeddedTokenSpaceGuid.PcdPrePiHobBase
gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize
gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress
gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize
gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData
[FeaturePcd]
gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob

View File

@@ -0,0 +1,327 @@
/** @file
Library that helps implement monolithic PEI
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 <PrePi.h>
#include <Library/ReportStatusCodeLib.h>
#include <Library/SerialPortLib.h>
#include <Library/PrintLib.h>
#include <Protocol/StatusCode.h>
#include <Guid/StatusCodeDataTypeId.h>
#include <Guid/StatusCodeDataTypeDebug.h>
#include <FrameworkPei.h>
#define EFI_STATUS_CODE_DATA_MAX_SIZE 200
EFI_STATUS
EFIAPI
SerialReportStatusCode (
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
IN CONST EFI_GUID *CallerId,
IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
);
EFI_STATUS_CODE_PROTOCOL gStatusCode = {
(EFI_REPORT_STATUS_CODE)SerialReportStatusCode
};
/**
Extracts ASSERT() information from a status code structure.
Converts the status code specified by CodeType, Value, and Data to the ASSERT()
arguments specified by Filename, Description, and LineNumber. If CodeType is
an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and
Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract
Filename, Description, and LineNumber from the optional data area of the
status code buffer specified by Data. The optional data area of Data contains
a Null-terminated ASCII string for the FileName, followed by a Null-terminated
ASCII string for the Description, followed by a 32-bit LineNumber. If the
ASSERT() information could be extracted from Data, then return TRUE.
Otherwise, FALSE is returned.
If Data is NULL, then ASSERT().
If Filename is NULL, then ASSERT().
If Description is NULL, then ASSERT().
If LineNumber is NULL, then ASSERT().
@param CodeType The type of status code being converted.
@param Value The status code value being converted.
@param Data Pointer to status code data buffer.
@param Filename Pointer to the source file name that generated the ASSERT().
@param Description Pointer to the description of the ASSERT().
@param LineNumber Pointer to source line number that generated the ASSERT().
@retval TRUE The status code specified by CodeType, Value, and Data was
converted ASSERT() arguments specified by Filename, Description,
and LineNumber.
@retval FALSE The status code specified by CodeType, Value, and Data could
not be converted to ASSERT() arguments.
**/
BOOLEAN
EFIAPI
ReportStatusCodeExtractAssertInfo (
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN CONST EFI_STATUS_CODE_DATA *Data,
OUT CHAR8 **Filename,
OUT CHAR8 **Description,
OUT UINT32 *LineNumber
)
{
EFI_DEBUG_ASSERT_DATA *AssertData;
ASSERT (Data != NULL);
ASSERT (Filename != NULL);
ASSERT (Description != NULL);
ASSERT (LineNumber != NULL);
if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) &&
((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) &&
((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) {
AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1);
*Filename = (CHAR8 *)(AssertData + 1);
*Description = *Filename + AsciiStrLen (*Filename) + 1;
*LineNumber = AssertData->LineNumber;
return TRUE;
}
return FALSE;
}
/**
Extracts DEBUG() information from a status code structure.
Converts the status code specified by Data to the DEBUG() arguments specified
by ErrorLevel, Marker, and Format. If type GUID in Data is
EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and
Format from the optional data area of the status code buffer specified by Data.
The optional data area of Data contains a 32-bit ErrorLevel followed by Marker
which is 12 UINTN parameters, followed by a Null-terminated ASCII string for
the Format. If the DEBUG() information could be extracted from Data, then
return TRUE. Otherwise, FALSE is returned.
If Data is NULL, then ASSERT().
If ErrorLevel is NULL, then ASSERT().
If Marker is NULL, then ASSERT().
If Format is NULL, then ASSERT().
@param Data Pointer to status code data buffer.
@param ErrorLevel Pointer to error level mask for a debug message.
@param Marker Pointer to the variable argument list associated with Format.
@param Format Pointer to a Null-terminated ASCII format string of a
debug message.
@retval TRUE The status code specified by Data was converted DEBUG() arguments
specified by ErrorLevel, Marker, and Format.
@retval FALSE The status code specified by Data could not be converted to
DEBUG() arguments.
**/
BOOLEAN
EFIAPI
ReportStatusCodeExtractDebugInfo (
IN CONST EFI_STATUS_CODE_DATA *Data,
OUT UINT32 *ErrorLevel,
OUT BASE_LIST *Marker,
OUT CHAR8 **Format
)
{
EFI_DEBUG_INFO *DebugInfo;
ASSERT (Data != NULL);
ASSERT (ErrorLevel != NULL);
ASSERT (Marker != NULL);
ASSERT (Format != NULL);
//
// If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE
//
if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) {
return FALSE;
}
//
// Retrieve the debug information from the status code record
//
DebugInfo = (EFI_DEBUG_INFO *)(Data + 1);
*ErrorLevel = DebugInfo->ErrorLevel;
//
// The first 12 * UINTN bytes of the string are really an
// argument stack to support varargs on the Format string.
//
*Marker = (BASE_LIST) (DebugInfo + 1);
*Format = (CHAR8 *)(((UINT64 *)*Marker) + 12);
return TRUE;
}
EFI_STATUS
EFIAPI
SerialReportStatusCode (
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
IN CONST EFI_GUID *CallerId,
IN CONST EFI_STATUS_CODE_DATA *Data OPTIONAL
)
{
CHAR8 *Filename;
CHAR8 *Description;
CHAR8 *Format;
CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE];
UINT32 ErrorLevel;
UINT32 LineNumber;
UINTN CharCount;
BASE_LIST Marker;
EFI_DEBUG_INFO *DebugInfo;
Buffer[0] = '\0';
if (Data != NULL &&
ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) {
//
// Print ASSERT() information into output buffer.
//
CharCount = AsciiSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
"\n\rASSERT!: %a (%d): %a\n\r",
Filename,
LineNumber,
Description
);
//
// Callout to standard output.
//
SerialPortWrite ((UINT8 *)Buffer, CharCount);
return EFI_SUCCESS;
} else if (Data != NULL &&
ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
//
// Print DEBUG() information into output buffer.
//
CharCount = AsciiBSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
Format,
Marker
);
} else if (Data != NULL &&
CompareGuid (&Data->Type, &gEfiStatusCodeSpecificDataGuid) &&
(CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
//
// Print specific data into output buffer.
//
DebugInfo = (EFI_DEBUG_INFO *) (Data + 1);
Marker = (BASE_LIST) (DebugInfo + 1);
Format = (CHAR8 *) (((UINT64 *) (DebugInfo + 1)) + 12);
CharCount = AsciiBSPrint (Buffer, EFI_STATUS_CODE_DATA_MAX_SIZE, Format, Marker);
} else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
//
// Print ERROR information into output buffer.
//
CharCount = AsciiSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
"ERROR: C%x:V%x I%x",
CodeType,
Value,
Instance
);
//
// Make sure we don't try to print values that weren't intended to be printed, especially NULL GUID pointers.
//
if (CallerId != NULL) {
CharCount += AsciiSPrint (
&Buffer[CharCount - 1],
(EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
" %g",
CallerId
);
}
if (Data != NULL) {
CharCount += AsciiSPrint (
&Buffer[CharCount - 1],
(EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
" %x",
Data
);
}
CharCount += AsciiSPrint (
&Buffer[CharCount - 1],
(EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)),
"\n\r"
);
} else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
CharCount = AsciiSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
"PROGRESS CODE: V%x I%x\n\r",
Value,
Instance
);
} else {
CharCount = AsciiSPrint (
Buffer,
EFI_STATUS_CODE_DATA_MAX_SIZE,
"Undefined: C%x:V%x I%x\n\r",
CodeType,
Value,
Instance
);
}
SerialPortWrite ((UINT8 *)Buffer, CharCount);
return EFI_SUCCESS;
}
VOID
EFIAPI
AddDxeCoreReportStatusCodeCallback (
VOID
)
{
BuildGuidDataHob (&gEfiStatusCodeRuntimeProtocolGuid, &gStatusCode, sizeof(VOID *));
}

View File

@@ -0,0 +1,258 @@
/** @file
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.
**/
/** @file
UEFI Debug Library that uses PrintLib to send messages to STDERR.
Copyright (c) 2006 - 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.
**/
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/PrintLib.h>
#include <Library/PcdLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/SemihostLib.h>
//
// Define the maximum debug and assert message length that this library supports
//
#define MAX_DEBUG_MESSAGE_LENGTH 0x100
/**
Prints a debug message to the debug output device if the specified error level is enabled.
If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print
the message specified by Format and the associated variable argument list to
the debug output device.
If Format is NULL, then ASSERT().
@param ErrorLevel The error level of the debug message.
@param Format Format string for the debug message to print.
**/
VOID
EFIAPI
DebugPrint (
IN UINTN ErrorLevel,
IN CONST CHAR8 *Format,
...
)
{
CHAR8 AsciiBuffer[MAX_DEBUG_MESSAGE_LENGTH];
VA_LIST Marker;
//
// If Format is NULL, then ASSERT().
//
ASSERT (Format != NULL);
//
// Check driver debug mask value and global mask
//
if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) {
return;
}
//
// Convert the DEBUG() message to a Unicode String
//
VA_START (Marker, Format);
AsciiVSPrint (AsciiBuffer, sizeof (AsciiBuffer), Format, Marker);
VA_END (Marker);
SemihostWriteString (AsciiBuffer);
}
/**
Prints an assert message containing a filename, line number, and description.
This may be followed by a breakpoint or a dead loop.
Print a message of the form "ASSERT <FileName>(<LineNumber>): <Description>\n"
to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
CpuDeadLoop() is called. If neither of these bits are set, then this function
returns immediately after the message is printed to the debug output device.
DebugAssert() must actively prevent recusrsion. If DebugAssert() is called while
processing another DebugAssert(), then DebugAssert() must return immediately.
If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
@param FileName Pointer to the name of the source file that generated the assert condition.
@param LineNumber The line number in the source file that generated the assert condition
@param Description Pointer to the description of the assert condition.
**/
VOID
EFIAPI
DebugAssert (
IN CONST CHAR8 *FileName,
IN UINTN LineNumber,
IN CONST CHAR8 *Description
)
{
CHAR8 AsciiBuffer[MAX_DEBUG_MESSAGE_LENGTH];
//
// Generate the ASSERT() message in Unicode format
//
AsciiSPrint (AsciiBuffer, sizeof (AsciiBuffer), "ASSERT %a(%d): %a\n", FileName, LineNumber, Description);
SemihostWriteString (AsciiBuffer);
//
// Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
//
if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
CpuBreakpoint ();
} else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
CpuDeadLoop ();
}
}
/**
Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
This function fills Length bytes of Buffer with the value specified by
PcdDebugClearMemoryValue, and returns Buffer.
If Buffer is NULL, then ASSERT().
If Length is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT().
@param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue.
@param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
@return Buffer
**/
VOID *
EFIAPI
DebugClearMemory (
OUT VOID *Buffer,
IN UINTN Length
)
{
//
// If Buffer is NULL, then ASSERT().
//
ASSERT (Buffer != NULL);
//
// SetMem() checks for the the ASSERT() condition on Length and returns Buffer
//
return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue));
}
/**
Returns TRUE if ASSERT() macros are enabled.
This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
PcdDebugProperyMask is set. Otherwise FALSE is returned.
@retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.
@retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.
**/
BOOLEAN
EFIAPI
DebugAssertEnabled (
VOID
)
{
return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);
}
/**
Returns TRUE if DEBUG()macros are enabled.
This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
PcdDebugProperyMask is set. Otherwise FALSE is returned.
@retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.
@retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.
**/
BOOLEAN
EFIAPI
DebugPrintEnabled (
VOID
)
{
return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
}
/**
Returns TRUE if DEBUG_CODE()macros are enabled.
This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
PcdDebugProperyMask is set. Otherwise FALSE is returned.
@retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.
@retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.
**/
BOOLEAN
EFIAPI
DebugCodeEnabled (
VOID
)
{
return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);
}
/**
Returns TRUE if DEBUG_CLEAR_MEMORY()macro is enabled.
This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of
PcdDebugProperyMask is set. Otherwise FALSE is returned.
@retval TRUE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.
@retval FALSE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.
**/
BOOLEAN
EFIAPI
DebugClearMemoryEnabled (
VOID
)
{
return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);
}

View File

@@ -0,0 +1,46 @@
#%HEADER%
#/** @file
# Debug Library for UEFI drivers
#
# Library to abstract Framework extensions that conflict with UEFI 2.0 Specification
# 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]
INF_VERSION = 0x00010005
BASE_NAME = SemiHostingDebugLib
FILE_GUID = 2A8D3FC4-8DB1-4D27-A3F3-780AF03CF848
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = DebugLib|BASE SEC DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
[Sources.common]
DebugLib.c
[Packages]
MdePkg/MdePkg.dec
ArmPkg/ArmPkg.dec
[LibraryClasses]
BaseMemoryLib
BaseLib
PcdLib
PrintLib
SemihostLib
[Pcd.common]
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel
gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask

View File

@@ -0,0 +1,35 @@
#%HEADER%
#/** @file
# Semihosting serail port lib
#
# Copyright (c) 2008, Apple Inc.
#
# 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]
INF_VERSION = 0x00010005
BASE_NAME = SemiHostingSerialPortLib
FILE_GUID = E9FB2D1E-05D9-421C-8C35-6100BB0093B7
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = SerialPortLib
[Sources.common]
SerialPortLib.c
[Packages]
MdePkg/MdePkg.dec
ArmPkg/ArmPkg.dec
[LibraryClasses]
SemihostLib

View File

@@ -0,0 +1,145 @@
/** @file
Serial I/O Port library functions with no library constructor/destructor
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 <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/SemihostLib.h>
#include <Library/SerialPortLib.h>
/*
Programmed hardware of Serial port.
@return Always return EFI_UNSUPPORTED.
**/
RETURN_STATUS
EFIAPI
SerialPortInitialize (
VOID
)
{
if (SemihostConnectionSupported ()) {
return RETURN_SUCCESS;
} else {
return RETURN_UNSUPPORTED;
}
}
/**
Write data to serial device.
@param Buffer Point of data buffer which need to be writed.
@param NumberOfBytes Number of output bytes which are cached in Buffer.
@retval 0 Write data failed.
@retval !0 Actual number of bytes writed to serial device.
**/
#define PRINT_BUFFER_SIZE 512
#define PRINT_BUFFER_THRESHOLD (PRINT_BUFFER_SIZE - 4)
UINTN
EFIAPI
SerialPortWrite (
IN UINT8 *Buffer,
IN UINTN NumberOfBytes
)
{
UINT8 PrintBuffer[PRINT_BUFFER_SIZE];
UINTN SourceIndex = 0;
UINTN DestinationIndex = 0;
UINT8 CurrentCharacter;
while (SourceIndex < NumberOfBytes)
{
CurrentCharacter = Buffer[SourceIndex++];
switch (CurrentCharacter)
{
case '\r':
continue;
case '\n':
PrintBuffer[DestinationIndex++] = ' ';
// fall through
default:
PrintBuffer[DestinationIndex++] = CurrentCharacter;
break;
}
if (DestinationIndex > PRINT_BUFFER_THRESHOLD)
{
PrintBuffer[DestinationIndex] = '\0';
SemihostWriteString ((CHAR8 *) PrintBuffer);
DestinationIndex = 0;
}
}
if (DestinationIndex > 0)
{
PrintBuffer[DestinationIndex] = '\0';
SemihostWriteString ((CHAR8 *) PrintBuffer);
}
return 0;
}
/**
Read data from serial device and save the datas in buffer.
@param Buffer Point of data buffer which need to be writed.
@param NumberOfBytes Number of output bytes which are cached in Buffer.
@retval 0 Read data failed.
@retval !0 Aactual number of bytes read from serial device.
**/
UINTN
EFIAPI
SerialPortRead (
OUT UINT8 *Buffer,
IN UINTN NumberOfBytes
)
{
*Buffer = SemihostReadCharacter ();
return 1;
}
/**
Check to see if any data is avaiable to be read from the debug device.
@retval TRUE At least one byte of data is avaiable to be read
@retval FALS No data is avaiable to be read
**/
BOOLEAN
EFIAPI
SerialPortPoll (
VOID
)
{
// Since SemiHosting read character is blocking always say we have a char ready?
return SemihostConnectionSupported ();
}

View File

@@ -0,0 +1,175 @@
/** @file
Implement EFI RealTimeClock runtime services via RTC Lib.
Currently this driver does not support runtime virtual calling.
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 <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
#include <Library/RealTimeClockLib.h>
/**
Returns the current time and date information, and the time-keeping capabilities
of the hardware platform.
@param Time A pointer to storage to receive a snapshot of the current time.
@param Capabilities An optional pointer to a buffer to receive the real time clock
device's capabilities.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER Time is NULL.
@retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
**/
EFI_STATUS
EFIAPI
LibGetTime (
OUT EFI_TIME *Time,
OUT EFI_TIME_CAPABILITIES *Capabilities
)
{
//
// Fill in Time and Capabilities via data from you RTC
//
return EFI_DEVICE_ERROR;
}
/**
Sets the current local time and date information.
@param Time A pointer to the current time.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER A time field is out of range.
@retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
**/
EFI_STATUS
EFIAPI
LibSetTime (
IN EFI_TIME *Time
)
{
//
// Use Time, to set the time in your RTC hardware
//
return EFI_DEVICE_ERROR;
}
/**
Returns the current wakeup alarm clock setting.
@param Enabled Indicates if the alarm is currently enabled or disabled.
@param Pending Indicates if the alarm signal is pending and requires acknowledgement.
@param Time The current alarm setting.
@retval EFI_SUCCESS The alarm settings were returned.
@retval EFI_INVALID_PARAMETER Any parameter is NULL.
@retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
**/
EFI_STATUS
EFIAPI
LibGetWakeupTime (
OUT BOOLEAN *Enabled,
OUT BOOLEAN *Pending,
OUT EFI_TIME *Time
)
{
// Not a required feature
return EFI_UNSUPPORTED;
}
/**
Sets the system wakeup alarm clock time.
@param Enabled Enable or disable the wakeup alarm.
@param Time If Enable is TRUE, the time to set the wakeup alarm for.
@retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
Enable is FALSE, then the wakeup alarm was disabled.
@retval EFI_INVALID_PARAMETER A time field is out of range.
@retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
@retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
**/
EFI_STATUS
EFIAPI
LibSetWakeupTime (
IN BOOLEAN Enabled,
OUT EFI_TIME *Time
)
{
// Not a required feature
return EFI_UNSUPPORTED;
}
/**
This is the declaration of an EFI image entry point. This can be the entry point to an application
written to this specification, an EFI boot service driver, or an EFI runtime driver.
@param ImageHandle Handle that identifies the loaded image.
@param SystemTable System Table for this image.
@retval EFI_SUCCESS The operation completed successfully.
**/
EFI_STATUS
EFIAPI
LibRtcInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
//
// Do some initialization if reqruied to turn on the RTC
//
return EFI_SUCCESS;
}
/**
Fixup internal data so that EFI can be call in virtual mode.
Call the passed in Child Notify event and convert any pointers in
lib to virtual mode.
@param[in] Event The Event that is being processed
@param[in] Context Event Context
**/
VOID
EFIAPI
LibRtcVirtualNotifyEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
//
// Only needed if you are going to support the OS calling RTC functions in virtual mode.
// You will need to call EfiConvertPointer (). To convert any stored physical addresses
// to virtual address. After the OS transistions to calling in virtual mode, all future
// runtime calls will be made in virtual mode.
//
return;
}

View File

@@ -0,0 +1,38 @@
#%HEADER%
#/** @file
# Memory Status Code Library for UEFI drivers
#
# Lib to provide memory journal status code reporting Routines
# Copyright (c) 2006, 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]
INF_VERSION = 0x00010005
BASE_NAME = TemplateRealTimeClockLib
FILE_GUID = B661E02D-A90B-42AB-A5F9-CF841AAA43D9
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = RealTimeClockLib
[Sources.common]
RealTimeClockLib.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
IoLib
DebugLib

View File

@@ -0,0 +1,103 @@
/** @file
Template library implementation to support ResetSystem Runtime call.
Fill in the templates with what ever makes you system reset.
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 <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/IoLib.h>
#include <Library/EfiResetSystemLib.h>
/**
Resets the entire platform.
@param ResetType The type of reset to perform.
@param ResetStatus The status code for the reset.
@param DataSize The size, in bytes, of WatchdogData.
@param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
EfiResetShutdown the data buffer starts with a Null-terminated
Unicode string, optionally followed by additional binary data.
**/
EFI_STATUS
EFIAPI
LibResetSystem (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN CHAR16 *ResetData OPTIONAL
)
{
UINTN Address;
UINT8 Data;
switch (ResetType) {
case EfiResetCold:
// system power cycle
// Example using IoLib functions to do IO.
Address = 0x12345678;
Data = MmioRead8 (Address);
MmioWrite8 (Address, Data | 0x01);
// Note this is a bad example asa MmioOr8 (Address, 0x01) does the same thing
break;
case EfiResetWarm:
// not a full power cycle, maybe memory stays around.
// if not support do the same thing as EfiResetCold.
break;
case EfiResetShutdown:
// turn off the system.
// if not support do the same thing as EfiResetCold.
break;
default:
return EFI_INVALID_PARAMETER;
}
//
// If we reset, we would not have returned...
//
return EFI_DEVICE_ERROR;
}
/**
Initialize any infrastructure required for LibResetSystem () to function.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
**/
EFI_STATUS
EFIAPI
LibInitializeResetSystem (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EFI_SUCCESS;
}

View File

@@ -0,0 +1,36 @@
#%HEADER%
#/** @file
# Memory Status Code Library for UEFI drivers
#
# Lib to provide memory journal status code reporting Routines
# Copyright (c) 2006, 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]
INF_VERSION = 0x00010005
BASE_NAME = TemplateResetSystemLib
FILE_GUID = 40BAFDE5-4CC8-4FBE-A8BA-071890076E50
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = EfiResetSystemLib
[Sources.common]
ResetSystemLib.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
IoLib
DebugLib

View File

@@ -0,0 +1,99 @@
/** @file
Serial I/O Port library functions with no library constructor/destructor
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 <Base.h>
#include <Library/SerialPortLib.h>
/*
Programmed hardware of Serial port.
@return Always return EFI_UNSUPPORTED.
**/
RETURN_STATUS
EFIAPI
SerialPortInitialize (
VOID
)
{
return RETURN_UNSUPPORTED;
}
/**
Write data to serial device.
@param Buffer Point of data buffer which need to be writed.
@param NumberOfBytes Number of output bytes which are cached in Buffer.
@retval 0 Write data failed.
@retval !0 Actual number of bytes writed to serial device.
**/
UINTN
EFIAPI
SerialPortWrite (
IN UINT8 *Buffer,
IN UINTN NumberOfBytes
)
{
return 0;
}
/**
Read data from serial device and save the datas in buffer.
@param Buffer Point of data buffer which need to be writed.
@param NumberOfBytes Number of output bytes which are cached in Buffer.
@retval 0 Read data failed.
@retval !0 Aactual number of bytes read from serial device.
**/
UINTN
EFIAPI
SerialPortRead (
OUT UINT8 *Buffer,
IN UINTN NumberOfBytes
)
{
return 0;
}
/**
Poll the serial device to see if there is any data waiting.
If there is data waiting to be read from the serial port, then return
TRUE. If there is no data waiting to be read from the serial port, then
return FALSE.
@retval TRUE Data is waiting to be read.
@retval FALSE There is no data waiting to be read.
**/
BOOLEAN
EFIAPI
SerialPortPoll (
VOID
)
{
return 0;
}

View File

@@ -0,0 +1,37 @@
#%HEADER%
#/** @file
# Memory Status Code Library for UEFI drivers
#
# Lib to provide memory journal status code reporting Routines
# Copyright (c) 2006, 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]
INF_VERSION = 0x00010005
BASE_NAME = TemplateSerialPortLib
FILE_GUID = A9133571-AD4B-4457-94A8-A9CC2CE7574F
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
LIBRARY_CLASS = SerialPortLib
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
TemplateSerialPortLib.c
[Packages]
MdePkg/MdePkg.dec

View File

@@ -0,0 +1,158 @@
/** @file
Implement EFI RealTimeClock runtime services via RTC Lib.
Currently this driver does not support runtime virtual calling.
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 <PiDxe.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/RealTimeClockLib.h>
#include <Protocol/RealTimeClock.h>
EFI_HANDLE mHandle = NULL;
/**
Returns the current time and date information, and the time-keeping capabilities
of the hardware platform.
@param Time A pointer to storage to receive a snapshot of the current time.
@param Capabilities An optional pointer to a buffer to receive the real time clock
device's capabilities.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER Time is NULL.
@retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
**/
EFI_STATUS
EFIAPI
GetTime (
OUT EFI_TIME *Time,
OUT EFI_TIME_CAPABILITIES *Capabilities
)
{
return LibGetTime (Time, Capabilities);
}
/**
Sets the current local time and date information.
@param Time A pointer to the current time.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER A time field is out of range.
@retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
**/
EFI_STATUS
EFIAPI
SetTime (
IN EFI_TIME *Time
)
{
return LibSetTime (Time);
}
/**
Returns the current wakeup alarm clock setting.
@param Enabled Indicates if the alarm is currently enabled or disabled.
@param Pending Indicates if the alarm signal is pending and requires acknowledgement.
@param Time The current alarm setting.
@retval EFI_SUCCESS The alarm settings were returned.
@retval EFI_INVALID_PARAMETER Any parameter is NULL.
@retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
**/
EFI_STATUS
EFIAPI
GetWakeupTime (
OUT BOOLEAN *Enabled,
OUT BOOLEAN *Pending,
OUT EFI_TIME *Time
)
{
return LibGetWakeupTime (Enabled, Pending, Time);
}
/**
Sets the system wakeup alarm clock time.
@param Enabled Enable or disable the wakeup alarm.
@param Time If Enable is TRUE, the time to set the wakeup alarm for.
@retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
Enable is FALSE, then the wakeup alarm was disabled.
@retval EFI_INVALID_PARAMETER A time field is out of range.
@retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
@retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
**/
EFI_STATUS
EFIAPI
SetWakeupTime (
IN BOOLEAN Enabled,
OUT EFI_TIME *Time
)
{
return LibSetWakeupTime (Enabled, Time);
}
/**
This is the declaration of an EFI image entry point. This can be the entry point to an application
written to this specification, an EFI boot service driver, or an EFI runtime driver.
@param ImageHandle Handle that identifies the loaded image.
@param SystemTable System Table for this image.
@retval EFI_SUCCESS The operation completed successfully.
**/
EFI_STATUS
EFIAPI
InitializeRealTimeClock (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
LibRtcInitialize (ImageHandle, SystemTable);
SystemTable->RuntimeServices->GetTime = GetTime;
SystemTable->RuntimeServices->SetTime = SetTime;
SystemTable->RuntimeServices->GetWakeupTime = GetWakeupTime;
SystemTable->RuntimeServices->SetWakeupTime = SetWakeupTime;
Status = gBS->InstallMultipleProtocolInterfaces (
&mHandle,
&gEfiRealTimeClockArchProtocolGuid,
NULL,
NULL
);
return Status;
}

View File

@@ -0,0 +1,45 @@
#%HEADER%
#/** @file
# NT Emulation Reset Architectural Protocol Driver as defined in TIANO
#
# This Reset module simulates system reset by process exit on NT.
# Copyright (c) 2006 - 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]
INF_VERSION = 0x00010005
BASE_NAME = RealTimeClock
FILE_GUID = B336F62D-4135-4A55-AE4E-4971BBF0885D
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = InitializeRealTimeClock
[Sources.common]
RealTimeClock.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
UefiBootServicesTableLib
UefiDriverEntryPoint
DebugLib
RealTimeClockLib
[Protocols]
gEfiRealTimeClockArchProtocolGuid
[Depex]
TRUE

View File

@@ -0,0 +1,51 @@
#%HEADER%
#/** @file
# NT Emulation Reset Architectural Protocol Driver as defined in TIANO
#
# This Reset module simulates system reset by process exit on NT.
# Copyright (c) 2006 - 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]
INF_VERSION = 0x00010005
BASE_NAME = Reset
FILE_GUID = 16036A73-E8EF-46D0-953C-9B8E96527D13
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = InitializeReset
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32
#
[Sources.common]
reset.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
UefiBootServicesTableLib
UefiDriverEntryPoint
DebugLib
EfiResetSystemLib
[Protocols]
gEfiResetArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED
[Depex]
TRUE

View File

@@ -0,0 +1,74 @@
/** @file
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 <PiDxe.h>
#include <Protocol/Reset.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/EfiResetSystemLib.h>
/**
Resets the entire platform.
@param ResetType The type of reset to perform.
@param ResetStatus The status code for the reset.
@param DataSize The size, in bytes, of WatchdogData.
@param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
EfiResetShutdown the data buffer starts with a Null-terminated
Unicode string, optionally followed by additional binary data.
**/
VOID
EFIAPI
ResetSystemViaLib (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN VOID *ResetData OPTIONAL
)
{
LibResetSystem (ResetType, ResetStatus, DataSize, ResetData);
return;
}
EFI_STATUS
EFIAPI
InitializeReset (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE Handle;
LibInitializeResetSystem (ImageHandle, SystemTable);
SystemTable->RuntimeServices->ResetSystem = ResetSystemViaLib;
Handle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEfiResetArchProtocolGuid,
NULL,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@@ -0,0 +1,54 @@
#%HEADER%
#/** @file
#
# Component discription file for Bds module
#
# Copyright (c) 2008, 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SerialDxe
FILE_GUID = D3987D4B-971A-435F-8CAF-4967EB627241
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = SerialDxeInitialize
[Sources.common]
SerialIo.c
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
BaseLib
ReportStatusCodeLib
MemoryAllocationLib
UefiLib
UefiBootServicesTableLib
BaseMemoryLib
DebugLib
UefiDriverEntryPoint
SerialPortLib
[Guids]
[Protocols]
gEfiSerialIoProtocolGuid
gEfiDevicePathProtocolGuid
[Depex]
TRUE

View File

@@ -0,0 +1,258 @@
/** @file
Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system
running GDB. One consle for error information and another console for user input/output.
Basic packet format is $packet-data#checksum. So every comand has 4 bytes of overhead: $,
#, 0, 0. The 0 and 0 are the ascii characters for the checksum.
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 <PiDxe.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/SerialPortLib.h>
#include <Protocol/SerialIo.h>
/**
Reset the serial device.
@param This Protocol instance pointer.
@retval EFI_SUCCESS The device was reset.
@retval EFI_DEVICE_ERROR The serial device could not be reset.
**/
EFI_STATUS
EFIAPI
SerialReset (
IN EFI_SERIAL_IO_PROTOCOL *This
)
{
SerialPortInitialize ();
return EFI_SUCCESS;
}
/**
Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
data buts, and stop bits on a serial device.
@param This Protocol instance pointer.
@param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
device's default interface speed.
@param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the
serial interface. A ReceiveFifoDepth value of 0 will use
the device's dfault FIFO depth.
@param Timeout The requested time out for a single character in microseconds.
This timeout applies to both the transmit and receive side of the
interface. A Timeout value of 0 will use the device's default time
out value.
@param Parity The type of parity to use on this serial device. A Parity value of
DefaultParity will use the device's default parity value.
@param DataBits The number of data bits to use on the serial device. A DataBits
vaule of 0 will use the device's default data bit setting.
@param StopBits The number of stop bits to use on this serial device. A StopBits
value of DefaultStopBits will use the device's default number of
stop bits.
@retval EFI_SUCCESS The device was reset.
@retval EFI_DEVICE_ERROR The serial device could not be reset.
**/
EFI_STATUS
EFIAPI
SerialSetAttributes (
IN EFI_SERIAL_IO_PROTOCOL *This,
IN UINT64 BaudRate,
IN UINT32 ReceiveFifoDepth,
IN UINT32 Timeout,
IN EFI_PARITY_TYPE Parity,
IN UINT8 DataBits,
IN EFI_STOP_BITS_TYPE StopBits
)
{
return EFI_UNSUPPORTED;
}
/**
Set the control bits on a serial device
@param This Protocol instance pointer.
@param Control Set the bits of Control that are settable.
@retval EFI_SUCCESS The new control bits were set on the serial device.
@retval EFI_UNSUPPORTED The serial device does not support this operation.
@retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
**/
EFI_STATUS
EFIAPI
SerialSetControl (
IN EFI_SERIAL_IO_PROTOCOL *This,
IN UINT32 Control
)
{
return EFI_UNSUPPORTED;
}
/**
Retrieves the status of thecontrol bits on a serial device
@param This Protocol instance pointer.
@param Control A pointer to return the current Control signals from the serial device.
@retval EFI_SUCCESS The control bits were read from the serial device.
@retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
**/
EFI_STATUS
EFIAPI
SerialGetControl (
IN EFI_SERIAL_IO_PROTOCOL *This,
OUT UINT32 *Control
)
{
if (SerialPortPoll ()) {
// If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY
*Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
} else {
*Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
}
return EFI_SUCCESS;
}
/**
Writes data to a serial device.
@param This Protocol instance pointer.
@param BufferSize On input, the size of the Buffer. On output, the amount of
data actually written.
@param Buffer The buffer of data to write
@retval EFI_SUCCESS The data was written.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_TIMEOUT The data write was stopped due to a timeout.
**/
EFI_STATUS
EFIAPI
SerialWrite (
IN EFI_SERIAL_IO_PROTOCOL *This,
IN OUT UINTN *BufferSize,
IN VOID *Buffer
)
{
UINTN Count;
Count = SerialPortWrite (Buffer, *BufferSize);
*BufferSize = Count;
return (Count == 0) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
}
/**
Writes data to a serial device.
@param This Protocol instance pointer.
@param BufferSize On input, the size of the Buffer. On output, the amount of
data returned in Buffer.
@param Buffer The buffer to return the data into.
@retval EFI_SUCCESS The data was read.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_TIMEOUT The data write was stopped due to a timeout.
**/
EFI_STATUS
EFIAPI
SerialRead (
IN EFI_SERIAL_IO_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
{
UINTN Count;
Count = SerialPortWrite (Buffer, *BufferSize);
*BufferSize = Count;
return (Count == 0) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
}
EFI_HANDLE gHandle = NULL;
//
// Template used to initailize the GDB Serial IO protocols
//
EFI_SERIAL_IO_MODE gSerialIoMode = {
0, // ControlMask
0, // Timeout
0, // BaudRate
1, // RceiveFifoDepth
0, // DataBits
0, // Parity
0 // StopBits
};
EFI_SERIAL_IO_PROTOCOL gSerialIoTemplate = {
SERIAL_IO_INTERFACE_REVISION,
SerialReset,
SerialSetAttributes,
SerialSetControl,
SerialGetControl,
SerialWrite,
SerialRead,
&gSerialIoMode
};
/**
Initialize the state information for the Serial Io Protocol
@param ImageHandle of the loaded driver
@param SystemTable Pointer to the System Table
@retval EFI_SUCCESS Protocol registered
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
@retval EFI_DEVICE_ERROR Hardware problems
**/
EFI_STATUS
EFIAPI
SerialDxeInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
// Make a new handle with Serial IO protocol and its device path on it.
Status = gBS->InstallMultipleProtocolInterfaces (
&gHandle,
&gEfiSerialIoProtocolGuid, &gSerialIoTemplate,
&gEfiDevicePathProtocolGuid, NULL, // BugBug: Need a device path
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@@ -0,0 +1,671 @@
/** @file
Simple Console that sits on a SerialLib.
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.
**/
/*
Symbols used in table below
===========================
ESC = 0x1B
CSI = 0x9B
DEL = 0x7f
^ = CTRL
+=========+======+===========+==========+==========+
| | EFI | UEFI 2.0 | | |
| | Scan | | VT100+ | |
| KEY | Code | PC ANSI | VTUTF8 | VT100 |
+=========+======+===========+==========+==========+
| NULL | 0x00 | | | |
| UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
| DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
| RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
| LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
| HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
| END | 0x06 | ESC [ F | ESC k | ESC [ K |
| INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
| | | ESC [ L | | ESC [ L |
| DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
| PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
| | | | | ESC [ ? |
| PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
| | | | | ESC [ / |
| F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
| F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
| F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
| F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
| F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
| F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
| F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
| F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
| F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
| F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
| Escape | 0x17 | ESC | ESC | ESC |
| F11 | 0x15 | | ESC ! | |
| F12 | 0x16 | | ESC @ | |
+=========+======+===========+==========+==========+
*/
#include <PiDxe.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/SerialPortLib.h>
#include <Protocol/SerialIo.h>
#include <Protocol/SimpleTextIn.h>
#include <Protocol/SimpleTextOut.h>
#define MODE0_COLUMN_COUNT 80
#define MODE0_ROW_COUNT 25
EFI_STATUS
EFIAPI
TextInReset(
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
EFI_STATUS
EFIAPI
ReadKeyStroke(
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
OUT EFI_INPUT_KEY *Key
);
EFI_STATUS
EFIAPI
TextOutReset(
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
CHAR8 *
EFIAPI
SafeUnicodeStrToAsciiStr (
IN CONST CHAR16 *Source,
OUT CHAR8 *Destination
);
EFI_STATUS
EFIAPI
OutputString (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
);
EFI_STATUS
EFIAPI
TestString (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
);
EFI_STATUS
EFIAPI
QueryMode (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN ModeNumber,
OUT UINTN *Columns,
OUT UINTN *Rows
);
EFI_STATUS
EFIAPI
SetMode(
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN ModeNumber
);
EFI_STATUS
EFIAPI
SetAttribute(
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN Attribute
);
EFI_STATUS
EFIAPI
ClearScreen (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
);
EFI_STATUS
EFIAPI
SetCursorPosition (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN Column,
IN UINTN Row
);
EFI_STATUS
EFIAPI
EnableCursor (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN BOOLEAN Enable
);
EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn = {
TextInReset,
ReadKeyStroke,
NULL
};
EFI_SIMPLE_TEXT_OUTPUT_MODE mSimpleTextOutMode = {
1,
0,
EFI_TEXT_ATTR( EFI_LIGHTGRAY, EFI_BLACK ),
0,
0,
TRUE
};
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mSimpleTextOut = {
TextOutReset,
OutputString,
TestString,
QueryMode,
SetMode,
SetAttribute,
ClearScreen,
SetCursorPosition,
EnableCursor,
&mSimpleTextOutMode
};
EFI_HANDLE mInstallHandle = NULL;
BOOLEAN
TextOutIsValidAscii (
IN CHAR16 Ascii
)
{
//
// valid ASCII code lies in the extent of 0x20 - 0x7F
//
if ((Ascii >= 0x20) && (Ascii <= 0x7F)) {
return TRUE;
}
return FALSE;
}
BOOLEAN
TextOutIsValidEfiCntlChar (
IN CHAR16 Char
)
{
//
// only support four control characters.
//
if (Char == CHAR_NULL ||
Char == CHAR_BACKSPACE ||
Char == CHAR_LINEFEED ||
Char == CHAR_CARRIAGE_RETURN ||
Char == CHAR_TAB ) {
return TRUE;
}
return FALSE;
}
VOID
EFIAPI
WaitForKeyEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
if (SerialPortPoll ()) {
gBS->SignalEvent (Event);
}
}
EFI_STATUS
EFIAPI
TextInReset (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
ReadKeyStroke (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
OUT EFI_INPUT_KEY *Key
)
{
CHAR8 Char;
SerialPortRead ((UINT8 *)&Char, 1);
//
// Check for ESC sequence. This code is not techincally correct VT100 code.
// An illegal ESC sequence represents an ESC and the characters that follow.
// This code will eat one or two chars after an escape. This is done to
// prevent some complex FIFOing of the data. It is good enough to get
// the arrow and delete keys working
//
Key->UnicodeChar = 0;
Key->ScanCode = SCAN_NULL;
if (Char == 0x1b) {
SerialPortRead ((UINT8 *)&Char, 1);
if (Char == '[') {
SerialPortRead ((UINT8 *)&Char, 1);
switch (Char) {
case 'A':
Key->ScanCode = SCAN_UP;
break;
case 'B':
Key->ScanCode = SCAN_DOWN;
break;
case 'C':
Key->ScanCode = SCAN_RIGHT;
break;
case 'D':
Key->ScanCode = SCAN_LEFT;
break;
case 'H':
Key->ScanCode = SCAN_HOME;
break;
case 'K':
case 'F': // PC ANSI
Key->ScanCode = SCAN_END;
break;
case '@':
case 'L':
Key->ScanCode = SCAN_INSERT;
break;
case 'P':
case 'X': // PC ANSI
Key->ScanCode = SCAN_DELETE;
break;
case 'U':
case '/':
case 'G': // PC ANSI
Key->ScanCode = SCAN_PAGE_DOWN;
break;
case 'V':
case '?':
case 'I': // PC ANSI
Key->ScanCode = SCAN_PAGE_UP;
break;
// PCANSI that does not conflict with VT100
case 'M':
Key->ScanCode = SCAN_F1;
break;
case 'N':
Key->ScanCode = SCAN_F2;
break;
case 'O':
Key->ScanCode = SCAN_F3;
break;
case 'Q':
Key->ScanCode = SCAN_F5;
break;
case 'R':
Key->ScanCode = SCAN_F6;
break;
case 'S':
Key->ScanCode = SCAN_F7;
break;
case 'T':
Key->ScanCode = SCAN_F8;
break;
default:
Key->UnicodeChar = Char;
break;
}
} else if (Char == '0') {
SerialPortRead ((UINT8 *)&Char, 1);
switch (Char) {
case 'P':
Key->ScanCode = SCAN_F1;
break;
case 'Q':
Key->ScanCode = SCAN_F2;
break;
case 'w':
Key->ScanCode = SCAN_F3;
break;
case 'x':
Key->ScanCode = SCAN_F4;
break;
case 't':
Key->ScanCode = SCAN_F5;
break;
case 'u':
Key->ScanCode = SCAN_F6;
break;
case 'q':
Key->ScanCode = SCAN_F7;
break;
case 'r':
Key->ScanCode = SCAN_F8;
break;
case 'p':
Key->ScanCode = SCAN_F9;
break;
case 'm':
Key->ScanCode = SCAN_F10;
break;
default :
break;
}
}
} else if (Char < ' ') {
if ((Char == CHAR_BACKSPACE) ||
(Char == CHAR_TAB) ||
(Char == CHAR_LINEFEED) ||
(Char == CHAR_CARRIAGE_RETURN)) {
// Only let through EFI required control characters
Key->UnicodeChar = (CHAR16)Char;
}
} else if (Char == 0x7f) {
Key->ScanCode = SCAN_DELETE;
} else {
Key->UnicodeChar = (CHAR16)Char;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
TextOutReset (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
EFI_STATUS Status;
This->SetAttribute(
This,
EFI_TEXT_ATTR(This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)
);
Status = This->SetMode (This, 0);
return Status;
}
CHAR8 *
EFIAPI
SafeUnicodeStrToAsciiStr (
IN CONST CHAR16 *Source,
OUT CHAR8 *Destination
)
{
CHAR8 *ReturnValue;
ASSERT (Destination != NULL);
//
// ASSERT if Source is long than PcdMaximumUnicodeStringLength.
// Length tests are performed inside StrLen().
//
ASSERT (StrSize (Source) != 0);
//
// Source and Destination should not overlap
//
ASSERT ((UINTN) ((CHAR16 *) Destination - Source) > StrLen (Source));
ASSERT ((UINTN) ((CHAR8 *) Source - Destination) > StrLen (Source));
ReturnValue = Destination;
while (*Source != '\0') {
//
// If any non-ascii characters in Source then replace it with '?'.
//
if (*Source < 0x80) {
*Destination = (CHAR8) *Source;
} else {
*Destination = '?';
//Surrogate pair check.
if ((*Source >= 0xD800) && (*Source <= 0xDFFF)) {
Source++;
}
}
Destination++;
Source++;
}
*Destination = '\0';
//
// ASSERT Original Destination is less long than PcdMaximumAsciiStringLength.
// Length tests are performed inside AsciiStrLen().
//
ASSERT (AsciiStrSize (ReturnValue) != 0);
return ReturnValue;
}
EFI_STATUS
EFIAPI
OutputString (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
)
{
UINTN Size = StrLen(String) + 1;
CHAR8 *OutputString = AllocatePool(Size);
//If there is any non-ascii characters in String buffer then replace it with '?'
//Eventually, UnicodeStrToAsciiStr API should be fixed.
SafeUnicodeStrToAsciiStr(String, OutputString);
SerialPortWrite ((UINT8 *)OutputString, Size - 1);
FreePool(OutputString);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
TestString (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN CHAR16 *String
)
{
CHAR8 Character;
for ( ; *String != CHAR_NULL; String++) {
Character = (CHAR8)*String;
if (!(TextOutIsValidAscii (Character) || TextOutIsValidEfiCntlChar (Character))) {
return EFI_UNSUPPORTED;
}
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
QueryMode (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN ModeNumber,
OUT UINTN *Columns,
OUT UINTN *Rows
)
{
if (This->Mode->MaxMode > 1) {
return EFI_DEVICE_ERROR;
}
if (ModeNumber == 0) {
*Columns = MODE0_COLUMN_COUNT;
*Rows = MODE0_ROW_COUNT;
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
SetMode (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN ModeNumber
)
{
if (ModeNumber != 0) {
return EFI_UNSUPPORTED;
}
This->Mode->Mode = 0;
This->ClearScreen (This);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
SetAttribute(
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN Attribute
)
{
This->Mode->Attribute = (INT32)Attribute;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
ClearScreen (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
)
{
EFI_STATUS Status;
Status = This->SetCursorPosition (This, 0, 0);
return Status;
}
EFI_STATUS
EFIAPI
SetCursorPosition (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN UINTN Column,
IN UINTN Row
)
{
EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
EFI_STATUS Status;
UINTN MaxColumn;
UINTN MaxRow;
Mode = This->Mode;
Status = This->QueryMode(
This,
Mode->Mode,
&MaxColumn,
&MaxRow
);
if (EFI_ERROR(Status)) {
return EFI_UNSUPPORTED;
}
if ((Column >= MaxColumn) || (Row >= MaxRow)) {
return EFI_UNSUPPORTED;
}
Mode->CursorColumn = (INT32)Column;
Mode->CursorRow = (INT32)Row;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
EnableCursor (
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
IN BOOLEAN Enable
)
{
if (!Enable) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
SimpleTextInOutEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
Status = gBS->CreateEvent (
EVT_NOTIFY_WAIT,
TPL_NOTIFY,
WaitForKeyEvent,
NULL,
&mSimpleTextIn.WaitForKey
);
ASSERT_EFI_ERROR (Status);
Status = gBS->InstallMultipleProtocolInterfaces(
&mInstallHandle,
&gEfiSimpleTextInProtocolGuid, &mSimpleTextIn,
&gEfiSimpleTextOutProtocolGuid, &mSimpleTextOut,
NULL
);
if (!EFI_ERROR (Status)) {
gST->ConOut = &mSimpleTextOut;
gST->ConIn = &mSimpleTextIn;
}
return Status;
}

View File

@@ -0,0 +1,56 @@
#%HEADER%
#/** @file
#
# Component discription file for Bds module
#
# Copyright (c) 2008, 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SimpleTextInOutSerial
FILE_GUID = 6696936D-3637-467C-87CB-14EA8248948C
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = SimpleTextInOutEntryPoint
[Sources.common]
SimpleTextInOut.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[LibraryClasses]
BaseLib
ReportStatusCodeLib
MemoryAllocationLib
UefiLib
UefiBootServicesTableLib
BaseMemoryLib
DebugLib
UefiDriverEntryPoint
SerialPortLib
[Guids]
[Protocols]
gEfiSimpleTextInProtocolGuid
gEfiSimpleTextOutProtocolGuid
gEfiSerialIoProtocolGuid
gEfiDevicePathProtocolGuid
[depex]
TRUE

View File

@@ -0,0 +1,183 @@
/** @file
The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements
of the UEFI specification as it is designed to implement an embedded systmes
propriatary boot scheme.
This template assume a DXE driver produces a SerialIo protocol not using the EFI
driver module and it will attempt to connect a console on top of this.
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 "BdsEntry.h"
BOOLEAN gConsolePresent = FALSE;
EFI_HANDLE mBdsImageHandle = NULL;
EFI_BDS_ARCH_PROTOCOL gBdsProtocol = {
BdsEntry,
};
/**
This function uses policy data from the platform to determine what operating
system or system utility should be loaded and invoked. This function call
also optionally make the use of user input to determine the operating system
or system utility to be loaded and invoked. When the DXE Core has dispatched
all the drivers on the dispatch queue, this function is called. This
function will attempt to connect the boot devices required to load and invoke
the selected operating system or system utility. During this process,
additional firmware volumes may be discovered that may contain addition DXE
drivers that can be dispatched by the DXE Core. If a boot device cannot be
fully connected, this function calls the DXE Service Dispatch() to allow the
DXE drivers from any newly discovered firmware volumes to be dispatched.
Then the boot device connection can be attempted again. If the same boot
device connection operation fails twice in a row, then that boot device has
failed, and should be skipped. This function should never return.
@param This The EFI_BDS_ARCH_PROTOCOL instance.
@return None.
**/
VOID
EFIAPI
BdsEntry (
IN EFI_BDS_ARCH_PROTOCOL *This
)
{
EFI_STATUS Status;
UINTN NoHandles;
EFI_HANDLE *Buffer;
UINTN Index;
EFI_HANDLE FvHandle;
EFI_GUID *NameGuid;
//
// This code assumes that a DXE driver produces a SerialIo protocol not following the EFI
// driver model. At a minimum we need to connect an EFI driver model terminal driver on top
// of the serial driver.
//
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Buffer);
if (!EFI_ERROR (Status)) {
for (Index = 0; Index < NoHandles; Index++) {
// For every Serial IO protocol in the system connect EFI drivers to it.
// This should cause the terminal driver to bind to the Serial IO protocol and produce a
// child handle that produces SimpleTextOut & SImpleTextIn protocols
gBS->ConnectController (Buffer[Index], NULL, NULL, TRUE);
}
FreePool (Buffer);
}
//
// Now we need to setup the EFI System Table with information about the console devices.
// This code is normally in the console spliter driver on platforms that support multiple
// consoles at the same time
//
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextOutProtocolGuid, NULL, &NoHandles, &Buffer);
if (!EFI_ERROR (Status)) {
// Use the first SimpleTextOut we find and update the EFI System Table
gST->ConsoleOutHandle = Buffer[0];
gST->StandardErrorHandle = Buffer[0];
Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextOutProtocolGuid, (VOID **)&gST->ConOut);
ASSERT_EFI_ERROR (Status);
gST->StdErr = gST->ConOut;
FreePool (Buffer);
gConsolePresent = TRUE;
}
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextInProtocolGuid, NULL, &NoHandles, &Buffer);
if (!EFI_ERROR (Status)) {
// Use the first SimpleTextIn we find and update the EFI System Table
gST->ConsoleInHandle = Buffer[0];
Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextInProtocolGuid, (VOID **)&gST->ConIn);
ASSERT_EFI_ERROR (Status);
FreePool (Buffer);
}
//
// We now have EFI Consoles up and running. Print () will work now. DEBUG () and ASSERT () worked
// prior to this point as they were configured to use a more primative output scheme.
//
//
// Platform specific stuff goes here
//
//
// Normal UEFI behavior is to process Globally Defined Variables as defined in Chapter 3
// (Boot Manager) of the UEFI specification. For this embedded system we don't do this.
//
//
// Search all the FVs for an application with a UI Section of Ebl. A .FDF file can be used
// to control the names of UI sections in an FV.
//
Status = FindApplicationMatchingUiSection (L"Ebl", &FvHandle, &NameGuid);
if (EFI_ERROR (Status)) {
//
// Just load the first application we find reguardless of name.
// This is the fallback path.
//
Status = FindApplicationMatchingUiSection (NULL, &FvHandle, &NameGuid);
// Nothing to boot
ASSERT_EFI_ERROR (Status);
}
Status = LoadPeCoffSectionFromFv (FvHandle, NameGuid);
//
// EFI does not define the bavior if all boot attemps fail and the last one returns.
// So we make a policy choice to reset the system since this BDS does not have a UI.
//
gRT->ResetSystem (EfiResetCold, Status, 0, NULL);
return ;
}
EFI_STATUS
EFIAPI
BdsInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
mBdsImageHandle = ImageHandle;
//
// Install protocol interface
//
Status = gBS->InstallMultipleProtocolInterfaces (
&mBdsImageHandle,
&gEfiBdsArchProtocolGuid, &gBdsProtocol,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@@ -0,0 +1,62 @@
/** @file
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 __BDS_ENTRY_H__
#define __BDS_ENTRY_H__
#include <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/PrintLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/HobLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PcdLib.h>
#include <Protocol/Bds.h>
#include <Protocol/SerialIo.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/SimpleTextIn.h>
#include <Protocol/SimpleTextOut.h>
EFI_STATUS
LoadPeCoffSectionFromFv (
IN EFI_HANDLE FvHandle,
IN EFI_GUID *NameGuid
);
EFI_STATUS
FindApplicationMatchingUiSection (
IN CHAR16 *UiString,
OUT EFI_HANDLE *FvHandle,
OUT EFI_GUID **NameGuid
);
VOID
EFIAPI
BdsEntry (
IN EFI_BDS_ARCH_PROTOCOL *This
);
#endif

View File

@@ -0,0 +1,160 @@
/** @file
The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements
of the UEFI specification as it is designed to implement an embedded systmes
propriatary boot scheme.
This template assume a DXE driver produces a SerialIo protocol not using the EFI
driver module and it will attempt to connect a console on top of this.
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 "BdsEntry.h"
EFI_STATUS
FindApplicationMatchingUiSection (
IN CHAR16 *UiString,
OUT EFI_HANDLE *FvHandle,
OUT EFI_GUID **NameGuid
)
{
EFI_STATUS Status;
EFI_STATUS NextStatus;
UINTN NoHandles;
EFI_HANDLE *Buffer;
UINTN Index;
EFI_FV_FILETYPE FileType;
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
VOID *Key;
EFI_FV_FILE_ATTRIBUTES Attributes;
UINTN Size;
UINTN UiStringLen;
CHAR16 *UiSection;
UINT32 Authentication;
UiStringLen = 0;
if (UiString != NULL) {
UiStringLen = StrLen (UiString);
}
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Buffer);
if (!EFI_ERROR (Status)) {
for (Index = 0; Index < NoHandles; Index++) {
Status = gBS->HandleProtocol (Buffer[Index], &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
if (!EFI_ERROR (Status)) {
Key = AllocatePool (Fv->KeySize);
FileType = EFI_FV_FILETYPE_APPLICATION;
do {
NextStatus = Fv->GetNextFile (Fv, Key, &FileType, *NameGuid, &Attributes, &Size);
if (!EFI_ERROR (NextStatus)) {
if (UiString == NULL) {
//
// If UiString is NULL match first application we find.
//
*FvHandle = Buffer[Index];
FreePool (Key);
return Status;
}
UiSection = NULL;
Status = Fv->ReadSection (
Fv,
*NameGuid,
EFI_SECTION_USER_INTERFACE,
0,
(VOID **)&UiSection,
&Size,
&Authentication
);
if (!EFI_ERROR (Status)) {
if (StrnCmp (UiString, UiSection, UiStringLen)) {
//
// We found a UiString match.
//
*FvHandle = Buffer[Index];
FreePool (Key);
FreePool (UiSection);
return Status;
}
FreePool (UiSection);
}
}
} while (!EFI_ERROR (NextStatus));
FreePool (Key);
}
}
FreePool (Buffer);
}
return EFI_NOT_FOUND;
}
EFI_DEVICE_PATH *
FvFileDevicePath (
IN EFI_HANDLE FvHandle,
IN EFI_GUID *NameGuid
)
{
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH NewNode;
DevicePath = DevicePathFromHandle (FvHandle);
EfiInitializeFwVolDevicepathNode (&NewNode, NameGuid);
return AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&NewNode);
}
EFI_STATUS
LoadPeCoffSectionFromFv (
IN EFI_HANDLE FvHandle,
IN EFI_GUID *NameGuid
)
{
EFI_STATUS Status;
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
VOID *Buffer;
UINTN BufferSize;
UINT32 Authentication;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_HANDLE ImageHandle;
Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
if (EFI_ERROR (Status)) {
return Status;
}
Status = Fv->ReadSection (Fv, NameGuid, EFI_SECTION_PE32, 0, &Buffer, &BufferSize, &Authentication);
if (!EFI_ERROR (Status)) {
DevicePath = FvFileDevicePath (FvHandle, NameGuid);
Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, Buffer, BufferSize, &ImageHandle);
if (!EFI_ERROR (Status)) {
// ExitData is NULL so we need to pass in a size of zero
BufferSize = 0;
Status = gBS->StartImage (ImageHandle, &BufferSize, NULL);
}
FreePool (Buffer);
}
return Status;
}

View File

@@ -0,0 +1,68 @@
#%HEADER%
#/** @file
#
# Component discription file for Bds module
#
# Copyright (c) 2008, 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = TemplateBds
FILE_GUID = 3C85595C-70FD-447D-B0CB-7F6BBA9C9BEB
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = BdsInitialize
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
BdsEntry.c
FirmwareVolume.c
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
DevicePathLib
BaseLib
HobLib
UefiRuntimeServicesTableLib
ReportStatusCodeLib
PerformanceLib
DxeServicesTableLib
MemoryAllocationLib
UefiLib
UefiBootServicesTableLib
BaseMemoryLib
DebugLib
PrintLib
UefiDriverEntryPoint
[Guids]
[Protocols]
gEfiBdsArchProtocolGuid
gEfiSimpleTextInProtocolGuid
gEfiSimpleTextOutProtocolGuid
gEfiSerialIoProtocolGuid
gEfiDevicePathProtocolGuid
gEfiFirmwareVolume2ProtocolGuid
[depex]
TRUE

View File

@@ -0,0 +1,250 @@
/** @file
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 <CpuDxe.h>
#include <Library/CacheMaintenanceLib.h>
VOID
ExceptionHandlersStart (
VOID
);
VOID
ExceptionHandlersEnd (
VOID
);
VOID
CommonExceptionEntry (
VOID
);
VOID
AsmCommonExceptionEntry (
VOID
);
EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1];
/**
This function registers and enables the handler specified by InterruptHandler for a processor
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
The installed handler is called once for each processor interrupt or exception.
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
are enabled and FALSE if interrupts are disabled.
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
when a processor interrupt occurs. If this parameter is NULL, then the handler
will be uninstalled.
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
previously installed.
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
previously installed.
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
**/
EFI_STATUS
RegisterInterruptHandler (
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
)
{
if (InterruptType > MAX_ARM_EXCEPTION) {
return EFI_UNSUPPORTED;
}
if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
return EFI_ALREADY_STARTED;
}
gExceptionHandlers[InterruptType] = InterruptHandler;
return EFI_SUCCESS;
}
VOID
EFIAPI
DefaultSWIExceptionHandler(
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext
)
{
return;
}
VOID
EFIAPI
DefaultExceptionHandler(
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext
)
{
DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextArm->PC));
ASSERT (FALSE);
return;
}
EFI_STATUS
InitializeExceptions (
IN EFI_CPU_ARCH_PROTOCOL *Cpu
)
{
EFI_STATUS Status = EFI_SUCCESS;
UINTN Offset;
UINTN Length;
UINTN Index;
BOOLEAN Enabled;
//
// Disable interrupts
//
Cpu->GetInterruptState (Cpu, &Enabled);
Cpu->DisableInterrupt (Cpu);
//
// Initialize the C entry points for interrupts
//
for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
if (Index == EXCEPT_ARM_SOFTWARE_INTERRUPT) {
Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultSWIExceptionHandler);
} else {
Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultExceptionHandler);
}
ASSERT_EFI_ERROR (Status);
}
//
// Copy an implementation of the ARM exception vectors to 0x0.
//
Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
CopyMem ((VOID *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress), (VOID *)ExceptionHandlersStart, Length);
//
// Patch in the common Assembly exception handler
//
Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
*(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
//
// Flush Caches since we updated executable stuff
//
InvalidateInstructionCache ();
if (Enabled) {
//
// Restore interrupt state
//
Status = Cpu->EnableInterrupt (Cpu);
}
return Status;
}
/**
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
must be between 0 and NumberOfTimers-1.
@param TimerValue Pointer to the returned timer value.
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
of TimerValue.
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
**/
EFI_STATUS
EFIAPI
GetTimerValue (
IN UINT32 TimerIndex,
OUT UINT64 *TimerValue,
OUT UINT64 *TimerPeriod OPTIONAL
)
{
return EFI_UNSUPPORTED;
}
/**
This function flushes the range of addresses from Start to Start+Length
from the processor's data cache. If Start is not aligned to a cache line
boundary, then the bytes before Start to the preceding cache line boundary
are also flushed. If Start+Length is not aligned to a cache line boundary,
then the bytes past Start+Length to the end of the next cache line boundary
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
supported. If the data cache is fully coherent with all DMA operations, then
this function can just return EFI_SUCCESS. If the processor does not support
flushing a range of the data cache, then the entire data cache can be flushed.
@param Start The beginning physical address to flush from the processor's data
cache.
@param Length The number of bytes to flush from the processor's data cache. This
function may flush more bytes than Length specifies depending upon
the granularity of the flush operation that the processor supports.
@param FlushType Specifies the type of flush operation to perform.
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
the processor's data cache.
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
by FlushType.
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
from the processor's data cache.
**/
EFI_STATUS
EFIAPI
FlushCpuDataCache (
IN EFI_PHYSICAL_ADDRESS Start,
IN UINT64 Length,
IN EFI_CPU_FLUSH_TYPE FlushType
)
{
if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
WriteBackInvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
return EFI_SUCCESS;
} else if (FlushType == EfiCpuFlushTypeInvalidate) {
InvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
return EFI_SUCCESS;
} else if (FlushType == EfiCpuFlushTypeWriteBack) {
WriteBackDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
return EFI_SUCCESS;
} else {
return EFI_UNSUPPORTED;
}
}

View File

@@ -0,0 +1,158 @@
#------------------------------------------------------------------------------
#
# 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.
#
#------------------------------------------------------------------------------
.text
.align 2
.globl _ExceptionHandlersStart
.globl _ExceptionHandlersEnd
.globl _CommonExceptionEntry
.globl _AsmCommonExceptionEntry
.globl _gExceptionHandlers
_ExceptionHandlersStart:
_Reset:
b _ResetEntry
_UndefinedInstruction:
b _UndefinedInstructionEntry
_SoftwareInterrupt:
b _SoftwareInterruptEntry
_PrefetchAbort:
b _PrefetchAbortEntry
_DataAbort:
b _DataAbortEntry
_ReservedException:
b _ReservedExceptionEntry
_Irq:
b _IrqEntry
_Fiq:
b _FiqEntry
_ResetEntry:
stmfd sp!,{r0-r1}
mov r0,#0
ldr r1,_CommonExceptionEntry
bx r1
_UndefinedInstructionEntry:
stmfd sp!,{r0-r1}
mov r0,#1
ldr r1,_CommonExceptionEntry
bx r1
_SoftwareInterruptEntry:
stmfd sp!,{r0-r1}
mov r0,#2
ldr r1,_CommonExceptionEntry
bx r1
_PrefetchAbortEntry:
stmfd sp!,{r0-r1}
mov r0,#3
sub lr,lr,#4
ldr r1,_CommonExceptionEntry
bx r1
_DataAbortEntry:
stmfd sp!,{r0-r1}
mov r0,#4
sub lr,lr,#8
ldr r1,_CommonExceptionEntry
bx r1
_ReservedExceptionEntry:
stmfd sp!,{r0-r1}
mov r0,#5
ldr r1,_CommonExceptionEntry
bx r1
_IrqEntry:
stmfd sp!,{r0-r1}
mov r0,#6
sub lr,lr,#4
ldr r1,_CommonExceptionEntry
bx r1
_FiqEntry:
stmfd sp!,{r0-r1}
mov r0,#7
sub lr,lr,#4
ldr r1,_CommonExceptionEntry
bx r1
_CommonExceptionEntry:
.byte 0x12
.byte 0x34
.byte 0x56
.byte 0x78
_ExceptionHandlersEnd:
LIndirectgExceptionHandlers:
.long _gExceptionHandlers
_AsmCommonExceptionEntry:
mrc p15, 0, r1, c6, c0, 2 @ Read IFAR
stmfd sp!,{r1} @ Store the IFAR
mrc p15, 0, r1, c5, c0, 1 @ Read IFSR
stmfd sp!,{r1} @ Store the IFSR
mrc p15, 0, r1, c6, c0, 0 @ Read DFAR
stmfd sp!,{r1} @ Store the DFAR
mrc p15, 0, r1, c5, c0, 0 @ Read DFSR
stmfd sp!,{r1} @ Store the DFSR
mrs r1,spsr @ Read SPSR (which is the pre-exception CPSR)
stmfd sp!,{r1} @ Store the SPSR
stmfd sp!,{lr} @ Store the link register (which is the pre-exception PC)
stmfd sp,{sp,lr}^ @ Store user/system mode stack pointer and link register
nop @ Required by ARM architecture
sub sp,sp,#0x08 @ Adjust stack pointer
stmfd sp!,{r2-r12} @ Store general purpose registers
ldr r3,[sp,#0x40] @ Read saved R1 from the stack (it was saved by the exception entry routine)
ldr r2,[sp,#0x3C] @ Read saved R0 from the stack (it was saved by the exception entry routine)
stmfd sp!,{r2-r3} @ Store general purpose registers R0 and R1
mov r1,sp @ Prepare System Context pointer as an argument for the exception handler
ldr r2,LIndirectgExceptionHandlers @ Offset to 32-bit address of exception handler
ldr r2,[r2] @ Load exception handler table
ldr r3,[r2,r0,lsl #2] @ Index to find the handler for this exception
// blx r3 @ Call exception handler
bx r3 @ Call exception handler
ldr r2,[sp,#0x40] @ Load CPSR from context, in case it has changed
msr SPSR_cxsf,r2 @ Store it back to the SPSR to be restored when exiting this handler
ldmfd sp!,{r0-r12} @ Restore general purpose registers
ldmia sp,{sp,lr}^ @ Restore user/system mode stack pointer and link register
nop @ Required by ARM architecture
add sp,sp,#0x08 @ Adjust stack pointer
ldmfd sp!,{lr} @ Restore the link register (which is the pre-exception PC)
add sp,sp,#0x1C @ Clear out the remaining stack space
movs pc,lr @ Return from exception

View File

@@ -0,0 +1,152 @@
//------------------------------------------------------------------------------
//
// 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.
//
//------------------------------------------------------------------------------
EXPORT ExceptionHandlersStart
EXPORT ExceptionHandlersEnd
EXPORT CommonExceptionEntry
EXPORT AsmCommonExceptionEntry
IMPORT gExceptionHandlers
AREA DxeExceptionHandlers, CODE, READONLY
ExceptionHandlersStart
Reset
B ResetEntry
UndefinedInstruction
B UndefinedInstructionEntry
SoftwareInterrupt
B SoftwareInterruptEntry
PrefetchAbort
B PrefetchAbortEntry
DataAbort
B DataAbortEntry
ReservedException
B ReservedExceptionEntry
Irq
B IrqEntry
Fiq
B FiqEntry
ResetEntry
STMFD SP!,{R0-R1}
MOV R0,#0
LDR R1,CommonExceptionEntry
BX R1
UndefinedInstructionEntry
STMFD SP!,{R0-R1}
MOV R0,#1
LDR R1,CommonExceptionEntry
BX R1
SoftwareInterruptEntry
STMFD SP!,{R0-R1}
MOV R0,#2
LDR R1,CommonExceptionEntry
BX R1
PrefetchAbortEntry
STMFD SP!,{R0-R1}
MOV R0,#3
SUB LR,LR,#4
LDR R1,CommonExceptionEntry
BX R1
DataAbortEntry
STMFD SP!,{R0-R1}
MOV R0,#4
SUB LR,LR,#8
LDR R1,CommonExceptionEntry
BX R1
ReservedExceptionEntry
STMFD SP!,{R0-R1}
MOV R0,#5
LDR R1,CommonExceptionEntry
BX R1
IrqEntry
STMFD SP!,{R0-R1}
MOV R0,#6
SUB LR,LR,#4
LDR R1,CommonExceptionEntry
BX R1
FiqEntry
STMFD SP!,{R0-R1}
MOV R0,#7
SUB LR,LR,#4
LDR R1,CommonExceptionEntry
BX R1
CommonExceptionEntry
DCD 0x12345678
ExceptionHandlersEnd
AsmCommonExceptionEntry
MRC p15, 0, r1, c6, c0, 2 ; Read IFAR
STMFD SP!,{R1} ; Store the IFAR
MRC p15, 0, r1, c5, c0, 1 ; Read IFSR
STMFD SP!,{R1} ; Store the IFSR
MRC p15, 0, r1, c6, c0, 0 ; Read DFAR
STMFD SP!,{R1} ; Store the DFAR
MRC p15, 0, r1, c5, c0, 0 ; Read DFSR
STMFD SP!,{R1} ; Store the DFSR
MRS R1,SPSR ; Read SPSR (which is the pre-exception CPSR)
STMFD SP!,{R1} ; Store the SPSR
STMFD SP!,{LR} ; Store the link register (which is the pre-exception PC)
STMFD SP,{SP,LR}^ ; Store user/system mode stack pointer and link register
NOP ; Required by ARM architecture
SUB SP,SP,#0x08 ; Adjust stack pointer
STMFD SP!,{R2-R12} ; Store general purpose registers
LDR R3,[SP,#0x40] ; Read saved R1 from the stack (it was saved by the exception entry routine)
LDR R2,[SP,#0x3C] ; Read saved R0 from the stack (it was saved by the exception entry routine)
STMFD SP!,{R2-R3} ; Store general purpose registers R0 and R1
MOV R1,SP ; Prepare System Context pointer as an argument for the exception handler
LDR R2,=gExceptionHandlers ; Load exception handler table
LDR R3,[R2,R0,LSL #2] ; Index to find the handler for this exception
BLX R3 ; Call exception handler
LDR R2,[SP,#0x40] ; Load CPSR from context, in case it has changed
MSR SPSR_cxsf,R2 ; Store it back to the SPSR to be restored when exiting this handler
LDMFD SP!,{R0-R12} ; Restore general purpose registers
LDM SP,{SP,LR}^ ; Restore user/system mode stack pointer and link register
NOP ; Required by ARM architecture
ADD SP,SP,#0x08 ; Adjust stack pointer
LDMFD SP!,{LR} ; Restore the link register (which is the pre-exception PC)
ADD SP,SP,#0x1C ; Clear out the remaining stack space
MOVS PC,LR ; Return from exception
END

View File

@@ -0,0 +1,323 @@
/** @file
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 "CpuDxe.h"
/**
This function flushes the range of addresses from Start to Start+Length
from the processor's data cache. If Start is not aligned to a cache line
boundary, then the bytes before Start to the preceding cache line boundary
are also flushed. If Start+Length is not aligned to a cache line boundary,
then the bytes past Start+Length to the end of the next cache line boundary
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
supported. If the data cache is fully coherent with all DMA operations, then
this function can just return EFI_SUCCESS. If the processor does not support
flushing a range of the data cache, then the entire data cache can be flushed.
@param This The EFI_CPU_ARCH_PROTOCOL instance.
@param Start The beginning physical address to flush from the processor's data
cache.
@param Length The number of bytes to flush from the processor's data cache. This
function may flush more bytes than Length specifies depending upon
the granularity of the flush operation that the processor supports.
@param FlushType Specifies the type of flush operation to perform.
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
the processor's data cache.
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
by FlushType.
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
from the processor's data cache.
**/
EFI_STATUS
EFIAPI
CpuFlushCpuDataCache (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN EFI_PHYSICAL_ADDRESS Start,
IN UINT64 Length,
IN EFI_CPU_FLUSH_TYPE FlushType
)
{
return FlushCpuDataCache (Start, Length, FlushType);
}
/**
This function enables interrupt processing by the processor.
@param This The EFI_CPU_ARCH_PROTOCOL instance.
@retval EFI_SUCCESS Interrupts are enabled on the processor.
@retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
**/
EFI_STATUS
EFIAPI
CpuEnableInterrupt (
IN EFI_CPU_ARCH_PROTOCOL *This
)
{
EnableInterrupts ();
return EFI_SUCCESS;
}
/**
This function disables interrupt processing by the processor.
@param This The EFI_CPU_ARCH_PROTOCOL instance.
@retval EFI_SUCCESS Interrupts are disabled on the processor.
@retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
**/
EFI_STATUS
EFIAPI
CpuDisableInterrupt (
IN EFI_CPU_ARCH_PROTOCOL *This
)
/*++
Routine Description:
Disables CPU interrupts.
Arguments:
This - Protocol instance structure
Returns:
EFI_SUCCESS - If interrupts were disabled in the CPU.
EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU.
--*/
{
DisableInterrupts ();
return EFI_SUCCESS;
}
/**
This function retrieves the processor's current interrupt state a returns it in
State. If interrupts are currently enabled, then TRUE is returned. If interrupts
are currently disabled, then FALSE is returned.
@param This The EFI_CPU_ARCH_PROTOCOL instance.
@param State A pointer to the processor's current interrupt state. Set to TRUE if
interrupts are enabled and FALSE if interrupts are disabled.
@retval EFI_SUCCESS The processor's current interrupt state was returned in State.
@retval EFI_INVALID_PARAMETER State is NULL.
**/
EFI_STATUS
EFIAPI
CpuGetInterruptState (
IN EFI_CPU_ARCH_PROTOCOL *This,
OUT BOOLEAN *State
)
{
if (State == NULL) {
return EFI_INVALID_PARAMETER;
}
*State = GetInterruptState ();
return EFI_SUCCESS;
}
/**
This function generates an INIT on the processor. If this function succeeds, then the
processor will be reset, and control will not be returned to the caller. If InitType is
not supported by this processor, or the processor cannot programmatically generate an
INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
@param This The EFI_CPU_ARCH_PROTOCOL instance.
@param InitType The type of processor INIT to perform.
@retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
@retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported
by this processor.
@retval EFI_DEVICE_ERROR The processor INIT failed.
**/
EFI_STATUS
EFIAPI
CpuInit (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN EFI_CPU_INIT_TYPE InitType
)
{
return EFI_UNSUPPORTED;
}
/**
This function registers and enables the handler specified by InterruptHandler for a processor
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
The installed handler is called once for each processor interrupt or exception.
@param This The EFI_CPU_ARCH_PROTOCOL instance.
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
are enabled and FALSE if interrupts are disabled.
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
when a processor interrupt occurs. If this parameter is NULL, then the handler
will be uninstalled.
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
previously installed.
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
previously installed.
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
**/
EFI_STATUS
EFIAPI
CpuRegisterInterruptHandler (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
)
{
return RegisterInterruptHandler (InterruptType, InterruptHandler);
}
/**
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
@param This The EFI_CPU_ARCH_PROTOCOL instance.
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
must be between 0 and NumberOfTimers-1.
@param TimerValue Pointer to the returned timer value.
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
of TimerValue.
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
**/
EFI_STATUS
EFIAPI
CpuGetTimerValue (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN UINT32 TimerIndex,
OUT UINT64 *TimerValue,
OUT UINT64 *TimerPeriod OPTIONAL
)
{
return GetTimerValue (TimerIndex, TimerValue, TimerPeriod);
}
/**
This function modifies the attributes for the memory region specified by BaseAddress and
Length from their current attributes to the attributes specified by Attributes.
@param This The EFI_CPU_ARCH_PROTOCOL instance.
@param BaseAddress The physical address that is the start address of a memory region.
@param Length The size in bytes of the memory region.
@param Attributes The bit mask of attributes to set for the memory region.
@retval EFI_SUCCESS The attributes were set for the memory region.
@retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
BaseAddress and Length cannot be modified.
@retval EFI_INVALID_PARAMETER Length is zero.
@retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
the memory resource range.
@retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
resource range specified by BaseAddress and Length.
The bit mask of attributes is not support for the memory resource
range specified by BaseAddress and Length.
**/
EFI_STATUS
EFIAPI
CpuSetMemoryAttributes (
IN EFI_CPU_ARCH_PROTOCOL *This,
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN UINT64 Attributes
)
{
//
// This is used to set cachability via the MMU on ARM
//
// This more about optimization and we can usually run fine if the default
// settings for cachability are good.
//
return EFI_UNSUPPORTED;
}
//
// Globals used to initialize the protocol
//
EFI_HANDLE mCpuHandle = NULL;
EFI_CPU_ARCH_PROTOCOL mCpu = {
CpuFlushCpuDataCache,
CpuEnableInterrupt,
CpuDisableInterrupt,
CpuGetInterruptState,
CpuInit,
CpuRegisterInterruptHandler,
CpuGetTimerValue,
CpuSetMemoryAttributes,
0, // NumberOfTimers
4, // DmaBufferAlignment
};
/**
Initialize the state information for the CPU Architectural Protocol
@param ImageHandle of the loaded driver
@param SystemTable Pointer to the System Table
@retval EFI_SUCCESS Protocol registered
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
@retval EFI_DEVICE_ERROR Hardware problems
**/
EFI_STATUS
CpuDxeInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
InitializeExceptions (&mCpu);
//
// Install CPU Architectural Protocol and the thunk protocol
//
Status = gBS->InstallMultipleProtocolInterfaces (
&mCpuHandle,
&gEfiCpuArchProtocolGuid, &mCpu,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@@ -0,0 +1,124 @@
/** @file
Copyright (c) 2006 - 2008, 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 <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/PcdLib.h>
#include <Protocol/Cpu.h>
#include <Protocol/DebugSupport.h>
/**
This function registers and enables the handler specified by InterruptHandler for a processor
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
The installed handler is called once for each processor interrupt or exception.
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
are enabled and FALSE if interrupts are disabled.
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
when a processor interrupt occurs. If this parameter is NULL, then the handler
will be uninstalled.
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
previously installed.
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
previously installed.
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
**/
EFI_STATUS
RegisterInterruptHandler (
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
);
EFI_STATUS
InitializeExceptions (
IN EFI_CPU_ARCH_PROTOCOL *Cpu
);
/**
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
must be between 0 and NumberOfTimers-1.
@param TimerValue Pointer to the returned timer value.
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
of TimerValue.
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
**/
EFI_STATUS
GetTimerValue (
IN UINT32 TimerIndex,
OUT UINT64 *TimerValue,
OUT UINT64 *TimerPeriod OPTIONAL
);
/**
This function flushes the range of addresses from Start to Start+Length
from the processor's data cache. If Start is not aligned to a cache line
boundary, then the bytes before Start to the preceding cache line boundary
are also flushed. If Start+Length is not aligned to a cache line boundary,
then the bytes past Start+Length to the end of the next cache line boundary
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
supported. If the data cache is fully coherent with all DMA operations, then
this function can just return EFI_SUCCESS. If the processor does not support
flushing a range of the data cache, then the entire data cache can be flushed.
@param Start The beginning physical address to flush from the processor's data
cache.
@param Length The number of bytes to flush from the processor's data cache. This
function may flush more bytes than Length specifies depending upon
the granularity of the flush operation that the processor supports.
@param FlushType Specifies the type of flush operation to perform.
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
the processor's data cache.
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
by FlushType.
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
from the processor's data cache.
**/
EFI_STATUS
EFIAPI
FlushCpuDataCache (
IN EFI_PHYSICAL_ADDRESS Start,
IN UINT64 Length,
IN EFI_CPU_FLUSH_TYPE FlushType
);

View File

@@ -0,0 +1,183 @@
/** @file
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 <CpuDxe.h>
EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100];
/**
This function registers and enables the handler specified by InterruptHandler for a processor
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
The installed handler is called once for each processor interrupt or exception.
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
are enabled and FALSE if interrupts are disabled.
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
when a processor interrupt occurs. If this parameter is NULL, then the handler
will be uninstalled.
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
previously installed.
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
previously installed.
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
**/
EFI_STATUS
RegisterInterruptHandler (
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
)
{
if (InterruptType > 0xFF) {
return EFI_UNSUPPORTED;
}
if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
return EFI_ALREADY_STARTED;
}
gExceptionHandlers[InterruptType] = InterruptHandler;
return EFI_SUCCESS;
}
VOID
EFIAPI
DefaultExceptionHandler (
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext
)
{
DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextIa32->Eip));
ASSERT (FALSE);
return;
}
EFI_STATUS
InitializeExceptions (
IN EFI_CPU_ARCH_PROTOCOL *Cpu
)
{
// You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler()
// and write all the assembly to handle the interrupts.
ASSERT (FALSE);
return EFI_UNSUPPORTED;
}
/**
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
must be between 0 and NumberOfTimers-1.
@param TimerValue Pointer to the returned timer value.
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
of TimerValue.
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
**/
EFI_STATUS
EFIAPI
GetTimerValue (
IN UINT32 TimerIndex,
OUT UINT64 *TimerValue,
OUT UINT64 *TimerPeriod OPTIONAL
)
{
if (TimerValue == NULL) {
return EFI_INVALID_PARAMETER;
}
if (TimerIndex == 0) {
*TimerValue = AsmReadTsc ();
if (TimerPeriod != NULL) {
//
// BugBug: Hard coded. Don't know how to do this generically
//
*TimerPeriod = 1000000000;
}
return EFI_SUCCESS;
}
return EFI_INVALID_PARAMETER;
}
/**
This function flushes the range of addresses from Start to Start+Length
from the processor's data cache. If Start is not aligned to a cache line
boundary, then the bytes before Start to the preceding cache line boundary
are also flushed. If Start+Length is not aligned to a cache line boundary,
then the bytes past Start+Length to the end of the next cache line boundary
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
supported. If the data cache is fully coherent with all DMA operations, then
this function can just return EFI_SUCCESS. If the processor does not support
flushing a range of the data cache, then the entire data cache can be flushed.
@param Start The beginning physical address to flush from the processor's data
cache.
@param Length The number of bytes to flush from the processor's data cache. This
function may flush more bytes than Length specifies depending upon
the granularity of the flush operation that the processor supports.
@param FlushType Specifies the type of flush operation to perform.
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
the processor's data cache.
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
by FlushType.
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
from the processor's data cache.
**/
EFI_STATUS
EFIAPI
FlushCpuDataCache (
IN EFI_PHYSICAL_ADDRESS Start,
IN UINT64 Length,
IN EFI_CPU_FLUSH_TYPE FlushType
)
{
if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
AsmWbinvd ();
return EFI_SUCCESS;
} else if (FlushType == EfiCpuFlushTypeInvalidate) {
AsmInvd ();
return EFI_SUCCESS;
} else {
return EFI_UNSUPPORTED;
}
}

View File

@@ -0,0 +1,71 @@
#%HEADER%
#/** @file
#
# Component discription file for Bds module
#
# Copyright (c) 2008, 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.
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = TemplateCpuDxe
FILE_GUID = CB6DC1E4-5B27-41E8-BC27-9AA50B62081E
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = CpuDxeInitialize
[Sources.common]
CpuDxe.c
[Sources.ARM]
Arm/Exception.c
Arm/Exceptions.asm
Arm/Exceptions.S
[Sources.IA32]
IA32/Exception.c
[Sources.X64]
X64/Exception.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
[Packages.ARM]
ArmPkg/ArmPkg.dec
[LibraryClasses]
BaseLib
UefiRuntimeServicesTableLib
ReportStatusCodeLib
PerformanceLib
DxeServicesTableLib
MemoryAllocationLib
UefiLib
UefiBootServicesTableLib
BaseMemoryLib
DebugLib
UefiDriverEntryPoint
CacheMaintenanceLib
[Protocols]
gEfiCpuArchProtocolGuid
[Pcd.ARM]
gArmTokenSpaceGuid.PcdCpuVectorBaseAddress
[depex]
TRUE

View File

@@ -0,0 +1,183 @@
/** @file
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 <CpuDxe.h>
EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100];
/**
This function registers and enables the handler specified by InterruptHandler for a processor
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
The installed handler is called once for each processor interrupt or exception.
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
are enabled and FALSE if interrupts are disabled.
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
when a processor interrupt occurs. If this parameter is NULL, then the handler
will be uninstalled.
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
previously installed.
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
previously installed.
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
**/
EFI_STATUS
RegisterInterruptHandler (
IN EFI_EXCEPTION_TYPE InterruptType,
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
)
{
if (InterruptType > 0xFF) {
return EFI_UNSUPPORTED;
}
if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
return EFI_ALREADY_STARTED;
}
gExceptionHandlers[InterruptType] = InterruptHandler;
return EFI_SUCCESS;
}
VOID
EFIAPI
DefaultExceptionHandler (
IN EFI_EXCEPTION_TYPE ExceptionType,
IN OUT EFI_SYSTEM_CONTEXT SystemContext
)
{
DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextX64->Rip));
ASSERT (FALSE);
return;
}
EFI_STATUS
InitializeExceptions (
IN EFI_CPU_ARCH_PROTOCOL *Cpu
)
{
// You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler()
// and write all the assembly to handle the interrupts.
ASSERT (FALSE);
return EFI_UNSUPPORTED;
}
/**
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
must be between 0 and NumberOfTimers-1.
@param TimerValue Pointer to the returned timer value.
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
of TimerValue.
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
**/
EFI_STATUS
EFIAPI
GetTimerValue (
IN UINT32 TimerIndex,
OUT UINT64 *TimerValue,
OUT UINT64 *TimerPeriod OPTIONAL
)
{
if (TimerValue == NULL) {
return EFI_INVALID_PARAMETER;
}
if (TimerIndex == 0) {
*TimerValue = AsmReadTsc ();
if (TimerPeriod != NULL) {
//
// BugBug: Hard coded. Don't know how to do this generically
//
*TimerPeriod = 1000000000;
}
return EFI_SUCCESS;
}
return EFI_INVALID_PARAMETER;
}
/**
This function flushes the range of addresses from Start to Start+Length
from the processor's data cache. If Start is not aligned to a cache line
boundary, then the bytes before Start to the preceding cache line boundary
are also flushed. If Start+Length is not aligned to a cache line boundary,
then the bytes past Start+Length to the end of the next cache line boundary
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
supported. If the data cache is fully coherent with all DMA operations, then
this function can just return EFI_SUCCESS. If the processor does not support
flushing a range of the data cache, then the entire data cache can be flushed.
@param Start The beginning physical address to flush from the processor's data
cache.
@param Length The number of bytes to flush from the processor's data cache. This
function may flush more bytes than Length specifies depending upon
the granularity of the flush operation that the processor supports.
@param FlushType Specifies the type of flush operation to perform.
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
the processor's data cache.
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
by FlushType.
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
from the processor's data cache.
**/
EFI_STATUS
EFIAPI
FlushCpuDataCache (
IN EFI_PHYSICAL_ADDRESS Start,
IN UINT64 Length,
IN EFI_CPU_FLUSH_TYPE FlushType
)
{
if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
AsmWbinvd ();
return EFI_SUCCESS;
} else if (FlushType == EfiCpuFlushTypeInvalidate) {
AsmInvd ();
return EFI_SUCCESS;
} else {
return EFI_UNSUPPORTED;
}
}

Some files were not shown because too many files have changed in this diff Show More