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,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