mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-29 08:34:07 +02:00
Remove Template stuff and teach people with BeagleBoard
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9876 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
e70c379327
commit
76a689b573
@ -1,183 +0,0 @@
|
|||||||
/** @file
|
|
||||||
The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements
|
|
||||||
of the UEFI specification as it is designed to implement an embedded systmes
|
|
||||||
propriatary boot scheme.
|
|
||||||
|
|
||||||
This template assume a DXE driver produces a SerialIo protocol not using the EFI
|
|
||||||
driver module and it will attempt to connect a console on top of this.
|
|
||||||
|
|
||||||
Copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
|
||||||
|
|
||||||
All rights reserved. This program and the accompanying materials
|
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
|
||||||
http://opensource.org/licenses/bsd-license.php
|
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include "BdsEntry.h"
|
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN gConsolePresent = FALSE;
|
|
||||||
|
|
||||||
|
|
||||||
EFI_HANDLE mBdsImageHandle = NULL;
|
|
||||||
EFI_BDS_ARCH_PROTOCOL gBdsProtocol = {
|
|
||||||
BdsEntry,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function uses policy data from the platform to determine what operating
|
|
||||||
system or system utility should be loaded and invoked. This function call
|
|
||||||
also optionally make the use of user input to determine the operating system
|
|
||||||
or system utility to be loaded and invoked. When the DXE Core has dispatched
|
|
||||||
all the drivers on the dispatch queue, this function is called. This
|
|
||||||
function will attempt to connect the boot devices required to load and invoke
|
|
||||||
the selected operating system or system utility. During this process,
|
|
||||||
additional firmware volumes may be discovered that may contain addition DXE
|
|
||||||
drivers that can be dispatched by the DXE Core. If a boot device cannot be
|
|
||||||
fully connected, this function calls the DXE Service Dispatch() to allow the
|
|
||||||
DXE drivers from any newly discovered firmware volumes to be dispatched.
|
|
||||||
Then the boot device connection can be attempted again. If the same boot
|
|
||||||
device connection operation fails twice in a row, then that boot device has
|
|
||||||
failed, and should be skipped. This function should never return.
|
|
||||||
|
|
||||||
@param This The EFI_BDS_ARCH_PROTOCOL instance.
|
|
||||||
|
|
||||||
@return None.
|
|
||||||
|
|
||||||
**/
|
|
||||||
VOID
|
|
||||||
EFIAPI
|
|
||||||
BdsEntry (
|
|
||||||
IN EFI_BDS_ARCH_PROTOCOL *This
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINTN NoHandles;
|
|
||||||
EFI_HANDLE *Buffer;
|
|
||||||
UINTN Index;
|
|
||||||
EFI_HANDLE FvHandle;
|
|
||||||
EFI_GUID *NameGuid;
|
|
||||||
|
|
||||||
//
|
|
||||||
// This code assumes that a DXE driver produces a SerialIo protocol not following the EFI
|
|
||||||
// driver model. At a minimum we need to connect an EFI driver model terminal driver on top
|
|
||||||
// of the serial driver.
|
|
||||||
//
|
|
||||||
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Buffer);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
for (Index = 0; Index < NoHandles; Index++) {
|
|
||||||
// For every Serial IO protocol in the system connect EFI drivers to it.
|
|
||||||
// This should cause the terminal driver to bind to the Serial IO protocol and produce a
|
|
||||||
// child handle that produces SimpleTextOut & SImpleTextIn protocols
|
|
||||||
gBS->ConnectController (Buffer[Index], NULL, NULL, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreePool (Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Now we need to setup the EFI System Table with information about the console devices.
|
|
||||||
// This code is normally in the console spliter driver on platforms that support multiple
|
|
||||||
// consoles at the same time
|
|
||||||
//
|
|
||||||
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextOutProtocolGuid, NULL, &NoHandles, &Buffer);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
// Use the first SimpleTextOut we find and update the EFI System Table
|
|
||||||
gST->ConsoleOutHandle = Buffer[0];
|
|
||||||
gST->StandardErrorHandle = Buffer[0];
|
|
||||||
Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextOutProtocolGuid, (VOID **)&gST->ConOut);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
gST->StdErr = gST->ConOut;
|
|
||||||
|
|
||||||
FreePool (Buffer);
|
|
||||||
|
|
||||||
gConsolePresent = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextInProtocolGuid, NULL, &NoHandles, &Buffer);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
// Use the first SimpleTextIn we find and update the EFI System Table
|
|
||||||
gST->ConsoleInHandle = Buffer[0];
|
|
||||||
Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextInProtocolGuid, (VOID **)&gST->ConIn);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
FreePool (Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// We now have EFI Consoles up and running. Print () will work now. DEBUG () and ASSERT () worked
|
|
||||||
// prior to this point as they were configured to use a more primative output scheme.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Platform specific stuff goes here
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Normal UEFI behavior is to process Globally Defined Variables as defined in Chapter 3
|
|
||||||
// (Boot Manager) of the UEFI specification. For this embedded system we don't do this.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Search all the FVs for an application with a UI Section of Ebl. A .FDF file can be used
|
|
||||||
// to control the names of UI sections in an FV.
|
|
||||||
//
|
|
||||||
Status = FindApplicationMatchingUiSection (L"Ebl", &FvHandle, &NameGuid);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
//
|
|
||||||
// Just load the first application we find reguardless of name.
|
|
||||||
// This is the fallback path.
|
|
||||||
//
|
|
||||||
Status = FindApplicationMatchingUiSection (NULL, &FvHandle, &NameGuid);
|
|
||||||
// Nothing to boot
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = LoadPeCoffSectionFromFv (FvHandle, NameGuid);
|
|
||||||
|
|
||||||
//
|
|
||||||
// EFI does not define the bavior if all boot attemps fail and the last one returns.
|
|
||||||
// So we make a policy choice to reset the system since this BDS does not have a UI.
|
|
||||||
//
|
|
||||||
gRT->ResetSystem (EfiResetCold, Status, 0, NULL);
|
|
||||||
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
BdsInitialize (
|
|
||||||
IN EFI_HANDLE ImageHandle,
|
|
||||||
IN EFI_SYSTEM_TABLE *SystemTable
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
mBdsImageHandle = ImageHandle;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Install protocol interface
|
|
||||||
//
|
|
||||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
||||||
&mBdsImageHandle,
|
|
||||||
&gEfiBdsArchProtocolGuid, &gBdsProtocol,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
|||||||
/** @file
|
|
||||||
|
|
||||||
Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
|
|
||||||
|
|
||||||
All rights reserved. This program and the accompanying materials
|
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
|
||||||
http://opensource.org/licenses/bsd-license.php
|
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef __BDS_ENTRY_H__
|
|
||||||
#define __BDS_ENTRY_H__
|
|
||||||
|
|
||||||
#include <PiDxe.h>
|
|
||||||
#include <Library/BaseLib.h>
|
|
||||||
#include <Library/DebugLib.h>
|
|
||||||
#include <Library/PrintLib.h>
|
|
||||||
#include <Library/BaseMemoryLib.h>
|
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
|
||||||
#include <Library/UefiLib.h>
|
|
||||||
#include <Library/MemoryAllocationLib.h>
|
|
||||||
#include <Library/DxeServicesTableLib.h>
|
|
||||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
||||||
#include <Library/HobLib.h>
|
|
||||||
#include <Library/DevicePathLib.h>
|
|
||||||
#include <Library/PcdLib.h>
|
|
||||||
|
|
||||||
#include <Protocol/Bds.h>
|
|
||||||
#include <Protocol/SerialIo.h>
|
|
||||||
#include <Protocol/FirmwareVolume2.h>
|
|
||||||
#include <Protocol/SimpleTextIn.h>
|
|
||||||
#include <Protocol/SimpleTextOut.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EFI_STATUS
|
|
||||||
LoadPeCoffSectionFromFv (
|
|
||||||
IN EFI_HANDLE FvHandle,
|
|
||||||
IN EFI_GUID *NameGuid
|
|
||||||
);
|
|
||||||
|
|
||||||
EFI_STATUS
|
|
||||||
FindApplicationMatchingUiSection (
|
|
||||||
IN CHAR16 *UiString,
|
|
||||||
OUT EFI_HANDLE *FvHandle,
|
|
||||||
OUT EFI_GUID **NameGuid
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
EFIAPI
|
|
||||||
BdsEntry (
|
|
||||||
IN EFI_BDS_ARCH_PROTOCOL *This
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,160 +0,0 @@
|
|||||||
/** @file
|
|
||||||
The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements
|
|
||||||
of the UEFI specification as it is designed to implement an embedded systmes
|
|
||||||
propriatary boot scheme.
|
|
||||||
|
|
||||||
This template assume a DXE driver produces a SerialIo protocol not using the EFI
|
|
||||||
driver module and it will attempt to connect a console on top of this.
|
|
||||||
|
|
||||||
Copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
|
||||||
|
|
||||||
All rights reserved. This program and the accompanying materials
|
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
|
||||||
http://opensource.org/licenses/bsd-license.php
|
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include "BdsEntry.h"
|
|
||||||
|
|
||||||
|
|
||||||
EFI_STATUS
|
|
||||||
FindApplicationMatchingUiSection (
|
|
||||||
IN CHAR16 *UiString,
|
|
||||||
OUT EFI_HANDLE *FvHandle,
|
|
||||||
OUT EFI_GUID **NameGuid
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
EFI_STATUS NextStatus;
|
|
||||||
UINTN NoHandles;
|
|
||||||
EFI_HANDLE *Buffer;
|
|
||||||
UINTN Index;
|
|
||||||
EFI_FV_FILETYPE FileType;
|
|
||||||
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
|
|
||||||
VOID *Key;
|
|
||||||
EFI_FV_FILE_ATTRIBUTES Attributes;
|
|
||||||
UINTN Size;
|
|
||||||
UINTN UiStringLen;
|
|
||||||
CHAR16 *UiSection;
|
|
||||||
UINT32 Authentication;
|
|
||||||
|
|
||||||
|
|
||||||
UiStringLen = 0;
|
|
||||||
if (UiString != NULL) {
|
|
||||||
UiStringLen = StrLen (UiString);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Buffer);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
for (Index = 0; Index < NoHandles; Index++) {
|
|
||||||
Status = gBS->HandleProtocol (Buffer[Index], &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
Key = AllocatePool (Fv->KeySize);
|
|
||||||
FileType = EFI_FV_FILETYPE_APPLICATION;
|
|
||||||
|
|
||||||
do {
|
|
||||||
NextStatus = Fv->GetNextFile (Fv, Key, &FileType, *NameGuid, &Attributes, &Size);
|
|
||||||
if (!EFI_ERROR (NextStatus)) {
|
|
||||||
if (UiString == NULL) {
|
|
||||||
//
|
|
||||||
// If UiString is NULL match first application we find.
|
|
||||||
//
|
|
||||||
*FvHandle = Buffer[Index];
|
|
||||||
FreePool (Key);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
UiSection = NULL;
|
|
||||||
Status = Fv->ReadSection (
|
|
||||||
Fv,
|
|
||||||
*NameGuid,
|
|
||||||
EFI_SECTION_USER_INTERFACE,
|
|
||||||
0,
|
|
||||||
(VOID **)&UiSection,
|
|
||||||
&Size,
|
|
||||||
&Authentication
|
|
||||||
);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
if (StrnCmp (UiString, UiSection, UiStringLen)) {
|
|
||||||
//
|
|
||||||
// We found a UiString match.
|
|
||||||
//
|
|
||||||
*FvHandle = Buffer[Index];
|
|
||||||
FreePool (Key);
|
|
||||||
FreePool (UiSection);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
FreePool (UiSection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!EFI_ERROR (NextStatus));
|
|
||||||
|
|
||||||
FreePool (Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FreePool (Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return EFI_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
EFI_DEVICE_PATH *
|
|
||||||
FvFileDevicePath (
|
|
||||||
IN EFI_HANDLE FvHandle,
|
|
||||||
IN EFI_GUID *NameGuid
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
||||||
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH NewNode;
|
|
||||||
|
|
||||||
DevicePath = DevicePathFromHandle (FvHandle);
|
|
||||||
|
|
||||||
EfiInitializeFwVolDevicepathNode (&NewNode, NameGuid);
|
|
||||||
|
|
||||||
return AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&NewNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EFI_STATUS
|
|
||||||
LoadPeCoffSectionFromFv (
|
|
||||||
IN EFI_HANDLE FvHandle,
|
|
||||||
IN EFI_GUID *NameGuid
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
|
|
||||||
VOID *Buffer;
|
|
||||||
UINTN BufferSize;
|
|
||||||
UINT32 Authentication;
|
|
||||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
||||||
EFI_HANDLE ImageHandle;
|
|
||||||
|
|
||||||
Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = Fv->ReadSection (Fv, NameGuid, EFI_SECTION_PE32, 0, &Buffer, &BufferSize, &Authentication);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
DevicePath = FvFileDevicePath (FvHandle, NameGuid);
|
|
||||||
Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, Buffer, BufferSize, &ImageHandle);
|
|
||||||
if (!EFI_ERROR (Status)) {
|
|
||||||
// ExitData is NULL so we need to pass in a size of zero
|
|
||||||
BufferSize = 0;
|
|
||||||
Status = gBS->StartImage (ImageHandle, &BufferSize, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreePool (Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
|||||||
#/** @file
|
|
||||||
#
|
|
||||||
# Component discription file for Bds module
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008, Intel Corporation. <BR>
|
|
||||||
# All rights reserved. This program and the accompanying materials
|
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
# which accompanies this distribution. The full text of the license may be found at
|
|
||||||
# http://opensource.org/licenses/bsd-license.php
|
|
||||||
#
|
|
||||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
#
|
|
||||||
#**/
|
|
||||||
|
|
||||||
[Defines]
|
|
||||||
INF_VERSION = 0x00010005
|
|
||||||
BASE_NAME = TemplateBds
|
|
||||||
FILE_GUID = 3C85595C-70FD-447D-B0CB-7F6BBA9C9BEB
|
|
||||||
MODULE_TYPE = DXE_DRIVER
|
|
||||||
VERSION_STRING = 1.0
|
|
||||||
|
|
||||||
ENTRY_POINT = BdsInitialize
|
|
||||||
|
|
||||||
#
|
|
||||||
# The following information is for reference only and not required by the build tools.
|
|
||||||
#
|
|
||||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
|
||||||
#
|
|
||||||
|
|
||||||
[Sources.common]
|
|
||||||
BdsEntry.c
|
|
||||||
FirmwareVolume.c
|
|
||||||
|
|
||||||
|
|
||||||
[Packages]
|
|
||||||
MdePkg/MdePkg.dec
|
|
||||||
|
|
||||||
[LibraryClasses]
|
|
||||||
DevicePathLib
|
|
||||||
BaseLib
|
|
||||||
HobLib
|
|
||||||
UefiRuntimeServicesTableLib
|
|
||||||
ReportStatusCodeLib
|
|
||||||
PerformanceLib
|
|
||||||
DxeServicesTableLib
|
|
||||||
MemoryAllocationLib
|
|
||||||
UefiLib
|
|
||||||
UefiBootServicesTableLib
|
|
||||||
BaseMemoryLib
|
|
||||||
DebugLib
|
|
||||||
PrintLib
|
|
||||||
UefiDriverEntryPoint
|
|
||||||
|
|
||||||
[Guids]
|
|
||||||
|
|
||||||
|
|
||||||
[Protocols]
|
|
||||||
gEfiBdsArchProtocolGuid
|
|
||||||
gEfiSimpleTextInProtocolGuid
|
|
||||||
gEfiSimpleTextOutProtocolGuid
|
|
||||||
gEfiSerialIoProtocolGuid
|
|
||||||
gEfiDevicePathProtocolGuid
|
|
||||||
gEfiFirmwareVolume2ProtocolGuid
|
|
||||||
|
|
||||||
[depex]
|
|
||||||
TRUE
|
|
@ -1,250 +0,0 @@
|
|||||||
/** @file
|
|
||||||
|
|
||||||
Copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
|
||||||
|
|
||||||
All rights reserved. This program and the accompanying materials
|
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
|
||||||
http://opensource.org/licenses/bsd-license.php
|
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include <CpuDxe.h>
|
|
||||||
#include <Library/CacheMaintenanceLib.h>
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ExceptionHandlersStart (
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
ExceptionHandlersEnd (
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
CommonExceptionEntry (
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
VOID
|
|
||||||
AsmCommonExceptionEntry (
|
|
||||||
VOID
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1];
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function registers and enables the handler specified by InterruptHandler for a processor
|
|
||||||
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
|
|
||||||
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
|
|
||||||
The installed handler is called once for each processor interrupt or exception.
|
|
||||||
|
|
||||||
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
|
|
||||||
are enabled and FALSE if interrupts are disabled.
|
|
||||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
|
|
||||||
when a processor interrupt occurs. If this parameter is NULL, then the handler
|
|
||||||
will be uninstalled.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
|
||||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
RegisterInterruptHandler (
|
|
||||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
|
||||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (InterruptType > MAX_ARM_EXCEPTION) {
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
|
|
||||||
return EFI_ALREADY_STARTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
gExceptionHandlers[InterruptType] = InterruptHandler;
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
EFIAPI
|
|
||||||
DefaultSWIExceptionHandler(
|
|
||||||
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
||||||
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
EFIAPI
|
|
||||||
DefaultExceptionHandler(
|
|
||||||
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
||||||
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextArm->PC));
|
|
||||||
ASSERT (FALSE);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EFI_STATUS
|
|
||||||
InitializeExceptions (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *Cpu
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status = EFI_SUCCESS;
|
|
||||||
UINTN Offset;
|
|
||||||
UINTN Length;
|
|
||||||
UINTN Index;
|
|
||||||
BOOLEAN Enabled;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Disable interrupts
|
|
||||||
//
|
|
||||||
Cpu->GetInterruptState (Cpu, &Enabled);
|
|
||||||
Cpu->DisableInterrupt (Cpu);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize the C entry points for interrupts
|
|
||||||
//
|
|
||||||
for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
|
|
||||||
if (Index == EXCEPT_ARM_SOFTWARE_INTERRUPT) {
|
|
||||||
Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultSWIExceptionHandler);
|
|
||||||
} else {
|
|
||||||
Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultExceptionHandler);
|
|
||||||
}
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Copy an implementation of the ARM exception vectors to 0x0.
|
|
||||||
//
|
|
||||||
Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
|
|
||||||
|
|
||||||
CopyMem ((VOID *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress), (VOID *)ExceptionHandlersStart, Length);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Patch in the common Assembly exception handler
|
|
||||||
//
|
|
||||||
Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
|
|
||||||
*(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Flush Caches since we updated executable stuff
|
|
||||||
//
|
|
||||||
InvalidateInstructionCache ();
|
|
||||||
|
|
||||||
if (Enabled) {
|
|
||||||
//
|
|
||||||
// Restore interrupt state
|
|
||||||
//
|
|
||||||
Status = Cpu->EnableInterrupt (Cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
|
|
||||||
|
|
||||||
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
|
|
||||||
must be between 0 and NumberOfTimers-1.
|
|
||||||
@param TimerValue Pointer to the returned timer value.
|
|
||||||
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
|
|
||||||
of TimerValue.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
|
|
||||||
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
|
|
||||||
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
GetTimerValue (
|
|
||||||
IN UINT32 TimerIndex,
|
|
||||||
OUT UINT64 *TimerValue,
|
|
||||||
OUT UINT64 *TimerPeriod OPTIONAL
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function flushes the range of addresses from Start to Start+Length
|
|
||||||
from the processor's data cache. If Start is not aligned to a cache line
|
|
||||||
boundary, then the bytes before Start to the preceding cache line boundary
|
|
||||||
are also flushed. If Start+Length is not aligned to a cache line boundary,
|
|
||||||
then the bytes past Start+Length to the end of the next cache line boundary
|
|
||||||
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
|
|
||||||
supported. If the data cache is fully coherent with all DMA operations, then
|
|
||||||
this function can just return EFI_SUCCESS. If the processor does not support
|
|
||||||
flushing a range of the data cache, then the entire data cache can be flushed.
|
|
||||||
|
|
||||||
@param Start The beginning physical address to flush from the processor's data
|
|
||||||
cache.
|
|
||||||
@param Length The number of bytes to flush from the processor's data cache. This
|
|
||||||
function may flush more bytes than Length specifies depending upon
|
|
||||||
the granularity of the flush operation that the processor supports.
|
|
||||||
@param FlushType Specifies the type of flush operation to perform.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
|
|
||||||
the processor's data cache.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
|
|
||||||
by FlushType.
|
|
||||||
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
|
|
||||||
from the processor's data cache.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
FlushCpuDataCache (
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Start,
|
|
||||||
IN UINT64 Length,
|
|
||||||
IN EFI_CPU_FLUSH_TYPE FlushType
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
|
|
||||||
WriteBackInvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
} else if (FlushType == EfiCpuFlushTypeInvalidate) {
|
|
||||||
InvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
} else if (FlushType == EfiCpuFlushTypeWriteBack) {
|
|
||||||
WriteBackDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
} else {
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
|||||||
#------------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
|
||||||
#
|
|
||||||
# All rights reserved. This program and the accompanying materials
|
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
# which accompanies this distribution. The full text of the license may be found at
|
|
||||||
# http://opensource.org/licenses/bsd-license.php
|
|
||||||
#
|
|
||||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
#
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
.text
|
|
||||||
.align 2
|
|
||||||
|
|
||||||
.globl _ExceptionHandlersStart
|
|
||||||
.globl _ExceptionHandlersEnd
|
|
||||||
.globl _CommonExceptionEntry
|
|
||||||
.globl _AsmCommonExceptionEntry
|
|
||||||
.globl _gExceptionHandlers
|
|
||||||
|
|
||||||
_ExceptionHandlersStart:
|
|
||||||
|
|
||||||
_Reset:
|
|
||||||
b _ResetEntry
|
|
||||||
|
|
||||||
_UndefinedInstruction:
|
|
||||||
b _UndefinedInstructionEntry
|
|
||||||
|
|
||||||
_SoftwareInterrupt:
|
|
||||||
b _SoftwareInterruptEntry
|
|
||||||
|
|
||||||
_PrefetchAbort:
|
|
||||||
b _PrefetchAbortEntry
|
|
||||||
|
|
||||||
_DataAbort:
|
|
||||||
b _DataAbortEntry
|
|
||||||
|
|
||||||
_ReservedException:
|
|
||||||
b _ReservedExceptionEntry
|
|
||||||
|
|
||||||
_Irq:
|
|
||||||
b _IrqEntry
|
|
||||||
|
|
||||||
_Fiq:
|
|
||||||
b _FiqEntry
|
|
||||||
|
|
||||||
_ResetEntry:
|
|
||||||
stmfd sp!,{r0-r1}
|
|
||||||
mov r0,#0
|
|
||||||
ldr r1,_CommonExceptionEntry
|
|
||||||
bx r1
|
|
||||||
|
|
||||||
_UndefinedInstructionEntry:
|
|
||||||
stmfd sp!,{r0-r1}
|
|
||||||
mov r0,#1
|
|
||||||
ldr r1,_CommonExceptionEntry
|
|
||||||
bx r1
|
|
||||||
|
|
||||||
_SoftwareInterruptEntry:
|
|
||||||
stmfd sp!,{r0-r1}
|
|
||||||
mov r0,#2
|
|
||||||
ldr r1,_CommonExceptionEntry
|
|
||||||
bx r1
|
|
||||||
|
|
||||||
_PrefetchAbortEntry:
|
|
||||||
stmfd sp!,{r0-r1}
|
|
||||||
mov r0,#3
|
|
||||||
sub lr,lr,#4
|
|
||||||
ldr r1,_CommonExceptionEntry
|
|
||||||
bx r1
|
|
||||||
|
|
||||||
_DataAbortEntry:
|
|
||||||
stmfd sp!,{r0-r1}
|
|
||||||
mov r0,#4
|
|
||||||
sub lr,lr,#8
|
|
||||||
ldr r1,_CommonExceptionEntry
|
|
||||||
bx r1
|
|
||||||
|
|
||||||
_ReservedExceptionEntry:
|
|
||||||
stmfd sp!,{r0-r1}
|
|
||||||
mov r0,#5
|
|
||||||
ldr r1,_CommonExceptionEntry
|
|
||||||
bx r1
|
|
||||||
|
|
||||||
_IrqEntry:
|
|
||||||
stmfd sp!,{r0-r1}
|
|
||||||
mov r0,#6
|
|
||||||
sub lr,lr,#4
|
|
||||||
ldr r1,_CommonExceptionEntry
|
|
||||||
bx r1
|
|
||||||
|
|
||||||
_FiqEntry:
|
|
||||||
stmfd sp!,{r0-r1}
|
|
||||||
mov r0,#7
|
|
||||||
sub lr,lr,#4
|
|
||||||
ldr r1,_CommonExceptionEntry
|
|
||||||
bx r1
|
|
||||||
|
|
||||||
_CommonExceptionEntry:
|
|
||||||
.byte 0x12
|
|
||||||
.byte 0x34
|
|
||||||
.byte 0x56
|
|
||||||
.byte 0x78
|
|
||||||
|
|
||||||
_ExceptionHandlersEnd:
|
|
||||||
|
|
||||||
LIndirectgExceptionHandlers:
|
|
||||||
.long _gExceptionHandlers
|
|
||||||
|
|
||||||
_AsmCommonExceptionEntry:
|
|
||||||
mrc p15, 0, r1, c6, c0, 2 @ Read IFAR
|
|
||||||
stmfd sp!,{r1} @ Store the IFAR
|
|
||||||
|
|
||||||
mrc p15, 0, r1, c5, c0, 1 @ Read IFSR
|
|
||||||
stmfd sp!,{r1} @ Store the IFSR
|
|
||||||
|
|
||||||
mrc p15, 0, r1, c6, c0, 0 @ Read DFAR
|
|
||||||
stmfd sp!,{r1} @ Store the DFAR
|
|
||||||
|
|
||||||
mrc p15, 0, r1, c5, c0, 0 @ Read DFSR
|
|
||||||
stmfd sp!,{r1} @ Store the DFSR
|
|
||||||
|
|
||||||
mrs r1,spsr @ Read SPSR (which is the pre-exception CPSR)
|
|
||||||
stmfd sp!,{r1} @ Store the SPSR
|
|
||||||
|
|
||||||
stmfd sp!,{lr} @ Store the link register (which is the pre-exception PC)
|
|
||||||
stmfd sp,{sp,lr}^ @ Store user/system mode stack pointer and link register
|
|
||||||
nop @ Required by ARM architecture
|
|
||||||
sub sp,sp,#0x08 @ Adjust stack pointer
|
|
||||||
stmfd sp!,{r2-r12} @ Store general purpose registers
|
|
||||||
|
|
||||||
ldr r3,[sp,#0x40] @ Read saved R1 from the stack (it was saved by the exception entry routine)
|
|
||||||
ldr r2,[sp,#0x3C] @ Read saved R0 from the stack (it was saved by the exception entry routine)
|
|
||||||
stmfd sp!,{r2-r3} @ Store general purpose registers R0 and R1
|
|
||||||
|
|
||||||
mov r1,sp @ Prepare System Context pointer as an argument for the exception handler
|
|
||||||
|
|
||||||
ldr r2,LIndirectgExceptionHandlers @ Offset to 32-bit address of exception handler
|
|
||||||
ldr r2,[r2] @ Load exception handler table
|
|
||||||
ldr r3,[r2,r0,lsl #2] @ Index to find the handler for this exception
|
|
||||||
|
|
||||||
// blx r3 @ Call exception handler
|
|
||||||
bx r3 @ Call exception handler
|
|
||||||
|
|
||||||
ldr r2,[sp,#0x40] @ Load CPSR from context, in case it has changed
|
|
||||||
msr SPSR_cxsf,r2 @ Store it back to the SPSR to be restored when exiting this handler
|
|
||||||
|
|
||||||
ldmfd sp!,{r0-r12} @ Restore general purpose registers
|
|
||||||
ldmia sp,{sp,lr}^ @ Restore user/system mode stack pointer and link register
|
|
||||||
nop @ Required by ARM architecture
|
|
||||||
add sp,sp,#0x08 @ Adjust stack pointer
|
|
||||||
ldmfd sp!,{lr} @ Restore the link register (which is the pre-exception PC)
|
|
||||||
add sp,sp,#0x1C @ Clear out the remaining stack space
|
|
||||||
movs pc,lr @ Return from exception
|
|
||||||
|
|
@ -1,152 +0,0 @@
|
|||||||
//------------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
// Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
// which accompanies this distribution. The full text of the license may be found at
|
|
||||||
// http://opensource.org/licenses/bsd-license.php
|
|
||||||
//
|
|
||||||
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
//
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
EXPORT ExceptionHandlersStart
|
|
||||||
EXPORT ExceptionHandlersEnd
|
|
||||||
EXPORT CommonExceptionEntry
|
|
||||||
EXPORT AsmCommonExceptionEntry
|
|
||||||
IMPORT gExceptionHandlers
|
|
||||||
|
|
||||||
AREA DxeExceptionHandlers, CODE, READONLY
|
|
||||||
|
|
||||||
ExceptionHandlersStart
|
|
||||||
|
|
||||||
Reset
|
|
||||||
B ResetEntry
|
|
||||||
|
|
||||||
UndefinedInstruction
|
|
||||||
B UndefinedInstructionEntry
|
|
||||||
|
|
||||||
SoftwareInterrupt
|
|
||||||
B SoftwareInterruptEntry
|
|
||||||
|
|
||||||
PrefetchAbort
|
|
||||||
B PrefetchAbortEntry
|
|
||||||
|
|
||||||
DataAbort
|
|
||||||
B DataAbortEntry
|
|
||||||
|
|
||||||
ReservedException
|
|
||||||
B ReservedExceptionEntry
|
|
||||||
|
|
||||||
Irq
|
|
||||||
B IrqEntry
|
|
||||||
|
|
||||||
Fiq
|
|
||||||
B FiqEntry
|
|
||||||
|
|
||||||
ResetEntry
|
|
||||||
STMFD SP!,{R0-R1}
|
|
||||||
MOV R0,#0
|
|
||||||
LDR R1,CommonExceptionEntry
|
|
||||||
BX R1
|
|
||||||
|
|
||||||
UndefinedInstructionEntry
|
|
||||||
STMFD SP!,{R0-R1}
|
|
||||||
MOV R0,#1
|
|
||||||
LDR R1,CommonExceptionEntry
|
|
||||||
BX R1
|
|
||||||
|
|
||||||
SoftwareInterruptEntry
|
|
||||||
STMFD SP!,{R0-R1}
|
|
||||||
MOV R0,#2
|
|
||||||
LDR R1,CommonExceptionEntry
|
|
||||||
BX R1
|
|
||||||
|
|
||||||
PrefetchAbortEntry
|
|
||||||
STMFD SP!,{R0-R1}
|
|
||||||
MOV R0,#3
|
|
||||||
SUB LR,LR,#4
|
|
||||||
LDR R1,CommonExceptionEntry
|
|
||||||
BX R1
|
|
||||||
|
|
||||||
DataAbortEntry
|
|
||||||
STMFD SP!,{R0-R1}
|
|
||||||
MOV R0,#4
|
|
||||||
SUB LR,LR,#8
|
|
||||||
LDR R1,CommonExceptionEntry
|
|
||||||
BX R1
|
|
||||||
|
|
||||||
ReservedExceptionEntry
|
|
||||||
STMFD SP!,{R0-R1}
|
|
||||||
MOV R0,#5
|
|
||||||
LDR R1,CommonExceptionEntry
|
|
||||||
BX R1
|
|
||||||
|
|
||||||
IrqEntry
|
|
||||||
STMFD SP!,{R0-R1}
|
|
||||||
MOV R0,#6
|
|
||||||
SUB LR,LR,#4
|
|
||||||
LDR R1,CommonExceptionEntry
|
|
||||||
BX R1
|
|
||||||
|
|
||||||
FiqEntry
|
|
||||||
STMFD SP!,{R0-R1}
|
|
||||||
MOV R0,#7
|
|
||||||
SUB LR,LR,#4
|
|
||||||
LDR R1,CommonExceptionEntry
|
|
||||||
BX R1
|
|
||||||
|
|
||||||
CommonExceptionEntry
|
|
||||||
DCD 0x12345678
|
|
||||||
|
|
||||||
ExceptionHandlersEnd
|
|
||||||
|
|
||||||
AsmCommonExceptionEntry
|
|
||||||
MRC p15, 0, r1, c6, c0, 2 ; Read IFAR
|
|
||||||
STMFD SP!,{R1} ; Store the IFAR
|
|
||||||
|
|
||||||
MRC p15, 0, r1, c5, c0, 1 ; Read IFSR
|
|
||||||
STMFD SP!,{R1} ; Store the IFSR
|
|
||||||
|
|
||||||
MRC p15, 0, r1, c6, c0, 0 ; Read DFAR
|
|
||||||
STMFD SP!,{R1} ; Store the DFAR
|
|
||||||
|
|
||||||
MRC p15, 0, r1, c5, c0, 0 ; Read DFSR
|
|
||||||
STMFD SP!,{R1} ; Store the DFSR
|
|
||||||
|
|
||||||
MRS R1,SPSR ; Read SPSR (which is the pre-exception CPSR)
|
|
||||||
STMFD SP!,{R1} ; Store the SPSR
|
|
||||||
|
|
||||||
STMFD SP!,{LR} ; Store the link register (which is the pre-exception PC)
|
|
||||||
STMFD SP,{SP,LR}^ ; Store user/system mode stack pointer and link register
|
|
||||||
NOP ; Required by ARM architecture
|
|
||||||
SUB SP,SP,#0x08 ; Adjust stack pointer
|
|
||||||
STMFD SP!,{R2-R12} ; Store general purpose registers
|
|
||||||
|
|
||||||
LDR R3,[SP,#0x40] ; Read saved R1 from the stack (it was saved by the exception entry routine)
|
|
||||||
LDR R2,[SP,#0x3C] ; Read saved R0 from the stack (it was saved by the exception entry routine)
|
|
||||||
STMFD SP!,{R2-R3} ; Store general purpose registers R0 and R1
|
|
||||||
|
|
||||||
MOV R1,SP ; Prepare System Context pointer as an argument for the exception handler
|
|
||||||
|
|
||||||
LDR R2,=gExceptionHandlers ; Load exception handler table
|
|
||||||
LDR R3,[R2,R0,LSL #2] ; Index to find the handler for this exception
|
|
||||||
|
|
||||||
BLX R3 ; Call exception handler
|
|
||||||
|
|
||||||
LDR R2,[SP,#0x40] ; Load CPSR from context, in case it has changed
|
|
||||||
MSR SPSR_cxsf,R2 ; Store it back to the SPSR to be restored when exiting this handler
|
|
||||||
|
|
||||||
LDMFD SP!,{R0-R12} ; Restore general purpose registers
|
|
||||||
LDM SP,{SP,LR}^ ; Restore user/system mode stack pointer and link register
|
|
||||||
NOP ; Required by ARM architecture
|
|
||||||
ADD SP,SP,#0x08 ; Adjust stack pointer
|
|
||||||
LDMFD SP!,{LR} ; Restore the link register (which is the pre-exception PC)
|
|
||||||
ADD SP,SP,#0x1C ; Clear out the remaining stack space
|
|
||||||
MOVS PC,LR ; Return from exception
|
|
||||||
|
|
||||||
END
|
|
||||||
|
|
||||||
|
|
@ -1,323 +0,0 @@
|
|||||||
/** @file
|
|
||||||
|
|
||||||
Copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
|
||||||
|
|
||||||
All rights reserved. This program and the accompanying materials
|
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
|
||||||
http://opensource.org/licenses/bsd-license.php
|
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include "CpuDxe.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function flushes the range of addresses from Start to Start+Length
|
|
||||||
from the processor's data cache. If Start is not aligned to a cache line
|
|
||||||
boundary, then the bytes before Start to the preceding cache line boundary
|
|
||||||
are also flushed. If Start+Length is not aligned to a cache line boundary,
|
|
||||||
then the bytes past Start+Length to the end of the next cache line boundary
|
|
||||||
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
|
|
||||||
supported. If the data cache is fully coherent with all DMA operations, then
|
|
||||||
this function can just return EFI_SUCCESS. If the processor does not support
|
|
||||||
flushing a range of the data cache, then the entire data cache can be flushed.
|
|
||||||
|
|
||||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
|
||||||
@param Start The beginning physical address to flush from the processor's data
|
|
||||||
cache.
|
|
||||||
@param Length The number of bytes to flush from the processor's data cache. This
|
|
||||||
function may flush more bytes than Length specifies depending upon
|
|
||||||
the granularity of the flush operation that the processor supports.
|
|
||||||
@param FlushType Specifies the type of flush operation to perform.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
|
|
||||||
the processor's data cache.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
|
|
||||||
by FlushType.
|
|
||||||
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
|
|
||||||
from the processor's data cache.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
CpuFlushCpuDataCache (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Start,
|
|
||||||
IN UINT64 Length,
|
|
||||||
IN EFI_CPU_FLUSH_TYPE FlushType
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return FlushCpuDataCache (Start, Length, FlushType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function enables interrupt processing by the processor.
|
|
||||||
|
|
||||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS Interrupts are enabled on the processor.
|
|
||||||
@retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
CpuEnableInterrupt (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *This
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EnableInterrupts ();
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function disables interrupt processing by the processor.
|
|
||||||
|
|
||||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS Interrupts are disabled on the processor.
|
|
||||||
@retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
CpuDisableInterrupt (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *This
|
|
||||||
)
|
|
||||||
/*++
|
|
||||||
|
|
||||||
Routine Description:
|
|
||||||
Disables CPU interrupts.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
This - Protocol instance structure
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
EFI_SUCCESS - If interrupts were disabled in the CPU.
|
|
||||||
EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU.
|
|
||||||
|
|
||||||
--*/
|
|
||||||
{
|
|
||||||
DisableInterrupts ();
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function retrieves the processor's current interrupt state a returns it in
|
|
||||||
State. If interrupts are currently enabled, then TRUE is returned. If interrupts
|
|
||||||
are currently disabled, then FALSE is returned.
|
|
||||||
|
|
||||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
|
||||||
@param State A pointer to the processor's current interrupt state. Set to TRUE if
|
|
||||||
interrupts are enabled and FALSE if interrupts are disabled.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The processor's current interrupt state was returned in State.
|
|
||||||
@retval EFI_INVALID_PARAMETER State is NULL.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
CpuGetInterruptState (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
|
||||||
OUT BOOLEAN *State
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (State == NULL) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
*State = GetInterruptState ();
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function generates an INIT on the processor. If this function succeeds, then the
|
|
||||||
processor will be reset, and control will not be returned to the caller. If InitType is
|
|
||||||
not supported by this processor, or the processor cannot programmatically generate an
|
|
||||||
INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
|
|
||||||
occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
|
|
||||||
|
|
||||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
|
||||||
@param InitType The type of processor INIT to perform.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
|
|
||||||
@retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported
|
|
||||||
by this processor.
|
|
||||||
@retval EFI_DEVICE_ERROR The processor INIT failed.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
CpuInit (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
|
||||||
IN EFI_CPU_INIT_TYPE InitType
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function registers and enables the handler specified by InterruptHandler for a processor
|
|
||||||
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
|
|
||||||
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
|
|
||||||
The installed handler is called once for each processor interrupt or exception.
|
|
||||||
|
|
||||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
|
||||||
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
|
|
||||||
are enabled and FALSE if interrupts are disabled.
|
|
||||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
|
|
||||||
when a processor interrupt occurs. If this parameter is NULL, then the handler
|
|
||||||
will be uninstalled.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
|
||||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
CpuRegisterInterruptHandler (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
|
||||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
|
||||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return RegisterInterruptHandler (InterruptType, InterruptHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
|
|
||||||
|
|
||||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
|
||||||
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
|
|
||||||
must be between 0 and NumberOfTimers-1.
|
|
||||||
@param TimerValue Pointer to the returned timer value.
|
|
||||||
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
|
|
||||||
of TimerValue.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
|
|
||||||
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
|
|
||||||
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
CpuGetTimerValue (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
|
||||||
IN UINT32 TimerIndex,
|
|
||||||
OUT UINT64 *TimerValue,
|
|
||||||
OUT UINT64 *TimerPeriod OPTIONAL
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return GetTimerValue (TimerIndex, TimerValue, TimerPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function modifies the attributes for the memory region specified by BaseAddress and
|
|
||||||
Length from their current attributes to the attributes specified by Attributes.
|
|
||||||
|
|
||||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
|
||||||
@param BaseAddress The physical address that is the start address of a memory region.
|
|
||||||
@param Length The size in bytes of the memory region.
|
|
||||||
@param Attributes The bit mask of attributes to set for the memory region.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The attributes were set for the memory region.
|
|
||||||
@retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
|
|
||||||
BaseAddress and Length cannot be modified.
|
|
||||||
@retval EFI_INVALID_PARAMETER Length is zero.
|
|
||||||
@retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
|
|
||||||
the memory resource range.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
|
|
||||||
resource range specified by BaseAddress and Length.
|
|
||||||
The bit mask of attributes is not support for the memory resource
|
|
||||||
range specified by BaseAddress and Length.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
CpuSetMemoryAttributes (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
|
||||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
|
||||||
IN UINT64 Length,
|
|
||||||
IN UINT64 Attributes
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// This is used to set cachability via the MMU on ARM
|
|
||||||
//
|
|
||||||
// This more about optimization and we can usually run fine if the default
|
|
||||||
// settings for cachability are good.
|
|
||||||
//
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Globals used to initialize the protocol
|
|
||||||
//
|
|
||||||
EFI_HANDLE mCpuHandle = NULL;
|
|
||||||
EFI_CPU_ARCH_PROTOCOL mCpu = {
|
|
||||||
CpuFlushCpuDataCache,
|
|
||||||
CpuEnableInterrupt,
|
|
||||||
CpuDisableInterrupt,
|
|
||||||
CpuGetInterruptState,
|
|
||||||
CpuInit,
|
|
||||||
CpuRegisterInterruptHandler,
|
|
||||||
CpuGetTimerValue,
|
|
||||||
CpuSetMemoryAttributes,
|
|
||||||
0, // NumberOfTimers
|
|
||||||
4, // DmaBufferAlignment
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Initialize the state information for the CPU Architectural Protocol
|
|
||||||
|
|
||||||
@param ImageHandle of the loaded driver
|
|
||||||
@param SystemTable Pointer to the System Table
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS Protocol registered
|
|
||||||
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
|
||||||
@retval EFI_DEVICE_ERROR Hardware problems
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
CpuDxeInitialize (
|
|
||||||
IN EFI_HANDLE ImageHandle,
|
|
||||||
IN EFI_SYSTEM_TABLE *SystemTable
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
InitializeExceptions (&mCpu);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Install CPU Architectural Protocol and the thunk protocol
|
|
||||||
//
|
|
||||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
||||||
&mCpuHandle,
|
|
||||||
&gEfiCpuArchProtocolGuid, &mCpu,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
@ -1,124 +0,0 @@
|
|||||||
/** @file
|
|
||||||
|
|
||||||
Copyright (c) 2006 - 2008, Intel Corporation <BR>
|
|
||||||
Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
|
||||||
|
|
||||||
All rights reserved. This program and the accompanying materials
|
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
|
||||||
http://opensource.org/licenses/bsd-license.php
|
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
#include <PiDxe.h>
|
|
||||||
|
|
||||||
#include <Library/BaseLib.h>
|
|
||||||
#include <Library/DebugLib.h>
|
|
||||||
#include <Library/BaseMemoryLib.h>
|
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
|
||||||
#include <Library/UefiLib.h>
|
|
||||||
#include <Library/MemoryAllocationLib.h>
|
|
||||||
#include <Library/DxeServicesTableLib.h>
|
|
||||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
||||||
#include <Library/PcdLib.h>
|
|
||||||
|
|
||||||
#include <Protocol/Cpu.h>
|
|
||||||
#include <Protocol/DebugSupport.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function registers and enables the handler specified by InterruptHandler for a processor
|
|
||||||
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
|
|
||||||
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
|
|
||||||
The installed handler is called once for each processor interrupt or exception.
|
|
||||||
|
|
||||||
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
|
|
||||||
are enabled and FALSE if interrupts are disabled.
|
|
||||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
|
|
||||||
when a processor interrupt occurs. If this parameter is NULL, then the handler
|
|
||||||
will be uninstalled.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
|
||||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
RegisterInterruptHandler (
|
|
||||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
|
||||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
EFI_STATUS
|
|
||||||
InitializeExceptions (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *Cpu
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
|
|
||||||
|
|
||||||
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
|
|
||||||
must be between 0 and NumberOfTimers-1.
|
|
||||||
@param TimerValue Pointer to the returned timer value.
|
|
||||||
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
|
|
||||||
of TimerValue.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
|
|
||||||
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
|
|
||||||
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
GetTimerValue (
|
|
||||||
IN UINT32 TimerIndex,
|
|
||||||
OUT UINT64 *TimerValue,
|
|
||||||
OUT UINT64 *TimerPeriod OPTIONAL
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function flushes the range of addresses from Start to Start+Length
|
|
||||||
from the processor's data cache. If Start is not aligned to a cache line
|
|
||||||
boundary, then the bytes before Start to the preceding cache line boundary
|
|
||||||
are also flushed. If Start+Length is not aligned to a cache line boundary,
|
|
||||||
then the bytes past Start+Length to the end of the next cache line boundary
|
|
||||||
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
|
|
||||||
supported. If the data cache is fully coherent with all DMA operations, then
|
|
||||||
this function can just return EFI_SUCCESS. If the processor does not support
|
|
||||||
flushing a range of the data cache, then the entire data cache can be flushed.
|
|
||||||
|
|
||||||
@param Start The beginning physical address to flush from the processor's data
|
|
||||||
cache.
|
|
||||||
@param Length The number of bytes to flush from the processor's data cache. This
|
|
||||||
function may flush more bytes than Length specifies depending upon
|
|
||||||
the granularity of the flush operation that the processor supports.
|
|
||||||
@param FlushType Specifies the type of flush operation to perform.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
|
|
||||||
the processor's data cache.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
|
|
||||||
by FlushType.
|
|
||||||
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
|
|
||||||
from the processor's data cache.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
FlushCpuDataCache (
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Start,
|
|
||||||
IN UINT64 Length,
|
|
||||||
IN EFI_CPU_FLUSH_TYPE FlushType
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
|||||||
/** @file
|
|
||||||
|
|
||||||
Copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
|
||||||
|
|
||||||
All rights reserved. This program and the accompanying materials
|
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
|
||||||
http://opensource.org/licenses/bsd-license.php
|
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include <CpuDxe.h>
|
|
||||||
|
|
||||||
|
|
||||||
EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100];
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function registers and enables the handler specified by InterruptHandler for a processor
|
|
||||||
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
|
|
||||||
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
|
|
||||||
The installed handler is called once for each processor interrupt or exception.
|
|
||||||
|
|
||||||
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
|
|
||||||
are enabled and FALSE if interrupts are disabled.
|
|
||||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
|
|
||||||
when a processor interrupt occurs. If this parameter is NULL, then the handler
|
|
||||||
will be uninstalled.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
|
||||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
RegisterInterruptHandler (
|
|
||||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
|
||||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (InterruptType > 0xFF) {
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
|
|
||||||
return EFI_ALREADY_STARTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
gExceptionHandlers[InterruptType] = InterruptHandler;
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
EFIAPI
|
|
||||||
DefaultExceptionHandler (
|
|
||||||
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
||||||
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextIa32->Eip));
|
|
||||||
ASSERT (FALSE);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EFI_STATUS
|
|
||||||
InitializeExceptions (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *Cpu
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler()
|
|
||||||
// and write all the assembly to handle the interrupts.
|
|
||||||
ASSERT (FALSE);
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
|
|
||||||
|
|
||||||
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
|
|
||||||
must be between 0 and NumberOfTimers-1.
|
|
||||||
@param TimerValue Pointer to the returned timer value.
|
|
||||||
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
|
|
||||||
of TimerValue.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
|
|
||||||
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
|
|
||||||
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
GetTimerValue (
|
|
||||||
IN UINT32 TimerIndex,
|
|
||||||
OUT UINT64 *TimerValue,
|
|
||||||
OUT UINT64 *TimerPeriod OPTIONAL
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (TimerValue == NULL) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TimerIndex == 0) {
|
|
||||||
*TimerValue = AsmReadTsc ();
|
|
||||||
if (TimerPeriod != NULL) {
|
|
||||||
//
|
|
||||||
// BugBug: Hard coded. Don't know how to do this generically
|
|
||||||
//
|
|
||||||
*TimerPeriod = 1000000000;
|
|
||||||
}
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function flushes the range of addresses from Start to Start+Length
|
|
||||||
from the processor's data cache. If Start is not aligned to a cache line
|
|
||||||
boundary, then the bytes before Start to the preceding cache line boundary
|
|
||||||
are also flushed. If Start+Length is not aligned to a cache line boundary,
|
|
||||||
then the bytes past Start+Length to the end of the next cache line boundary
|
|
||||||
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
|
|
||||||
supported. If the data cache is fully coherent with all DMA operations, then
|
|
||||||
this function can just return EFI_SUCCESS. If the processor does not support
|
|
||||||
flushing a range of the data cache, then the entire data cache can be flushed.
|
|
||||||
|
|
||||||
@param Start The beginning physical address to flush from the processor's data
|
|
||||||
cache.
|
|
||||||
@param Length The number of bytes to flush from the processor's data cache. This
|
|
||||||
function may flush more bytes than Length specifies depending upon
|
|
||||||
the granularity of the flush operation that the processor supports.
|
|
||||||
@param FlushType Specifies the type of flush operation to perform.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
|
|
||||||
the processor's data cache.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
|
|
||||||
by FlushType.
|
|
||||||
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
|
|
||||||
from the processor's data cache.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
FlushCpuDataCache (
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Start,
|
|
||||||
IN UINT64 Length,
|
|
||||||
IN EFI_CPU_FLUSH_TYPE FlushType
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
|
|
||||||
AsmWbinvd ();
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
} else if (FlushType == EfiCpuFlushTypeInvalidate) {
|
|
||||||
AsmInvd ();
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
} else {
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,70 +0,0 @@
|
|||||||
#/** @file
|
|
||||||
#
|
|
||||||
# Component discription file for Bds module
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008, Intel Corporation. <BR>
|
|
||||||
# All rights reserved. This program and the accompanying materials
|
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
# which accompanies this distribution. The full text of the license may be found at
|
|
||||||
# http://opensource.org/licenses/bsd-license.php
|
|
||||||
#
|
|
||||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
#
|
|
||||||
#**/
|
|
||||||
|
|
||||||
[Defines]
|
|
||||||
INF_VERSION = 0x00010005
|
|
||||||
BASE_NAME = TemplateCpuDxe
|
|
||||||
FILE_GUID = CB6DC1E4-5B27-41E8-BC27-9AA50B62081E
|
|
||||||
MODULE_TYPE = DXE_DRIVER
|
|
||||||
VERSION_STRING = 1.0
|
|
||||||
|
|
||||||
ENTRY_POINT = CpuDxeInitialize
|
|
||||||
|
|
||||||
|
|
||||||
[Sources.common]
|
|
||||||
CpuDxe.c
|
|
||||||
|
|
||||||
[Sources.ARM]
|
|
||||||
Arm/Exception.c
|
|
||||||
Arm/Exceptions.asm
|
|
||||||
Arm/Exceptions.S
|
|
||||||
|
|
||||||
[Sources.IA32]
|
|
||||||
IA32/Exception.c
|
|
||||||
|
|
||||||
[Sources.X64]
|
|
||||||
X64/Exception.c
|
|
||||||
|
|
||||||
|
|
||||||
[Packages]
|
|
||||||
MdePkg/MdePkg.dec
|
|
||||||
EmbeddedPkg/EmbeddedPkg.dec
|
|
||||||
|
|
||||||
[Packages.ARM]
|
|
||||||
ArmPkg/ArmPkg.dec
|
|
||||||
|
|
||||||
[LibraryClasses]
|
|
||||||
BaseLib
|
|
||||||
UefiRuntimeServicesTableLib
|
|
||||||
ReportStatusCodeLib
|
|
||||||
PerformanceLib
|
|
||||||
DxeServicesTableLib
|
|
||||||
MemoryAllocationLib
|
|
||||||
UefiLib
|
|
||||||
UefiBootServicesTableLib
|
|
||||||
BaseMemoryLib
|
|
||||||
DebugLib
|
|
||||||
UefiDriverEntryPoint
|
|
||||||
CacheMaintenanceLib
|
|
||||||
|
|
||||||
[Protocols]
|
|
||||||
gEfiCpuArchProtocolGuid
|
|
||||||
|
|
||||||
[Pcd.ARM]
|
|
||||||
gArmTokenSpaceGuid.PcdCpuVectorBaseAddress
|
|
||||||
|
|
||||||
|
|
||||||
[depex]
|
|
||||||
TRUE
|
|
@ -1,183 +0,0 @@
|
|||||||
/** @file
|
|
||||||
|
|
||||||
Copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
|
||||||
|
|
||||||
All rights reserved. This program and the accompanying materials
|
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
|
||||||
http://opensource.org/licenses/bsd-license.php
|
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include <CpuDxe.h>
|
|
||||||
|
|
||||||
|
|
||||||
EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100];
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function registers and enables the handler specified by InterruptHandler for a processor
|
|
||||||
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
|
|
||||||
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
|
|
||||||
The installed handler is called once for each processor interrupt or exception.
|
|
||||||
|
|
||||||
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
|
|
||||||
are enabled and FALSE if interrupts are disabled.
|
|
||||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
|
|
||||||
when a processor interrupt occurs. If this parameter is NULL, then the handler
|
|
||||||
will be uninstalled.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
|
||||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
|
|
||||||
previously installed.
|
|
||||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
RegisterInterruptHandler (
|
|
||||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
|
||||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (InterruptType > 0xFF) {
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
|
|
||||||
return EFI_ALREADY_STARTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
gExceptionHandlers[InterruptType] = InterruptHandler;
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
EFIAPI
|
|
||||||
DefaultExceptionHandler (
|
|
||||||
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
||||||
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextX64->Rip));
|
|
||||||
ASSERT (FALSE);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EFI_STATUS
|
|
||||||
InitializeExceptions (
|
|
||||||
IN EFI_CPU_ARCH_PROTOCOL *Cpu
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler()
|
|
||||||
// and write all the assembly to handle the interrupts.
|
|
||||||
ASSERT (FALSE);
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
|
|
||||||
|
|
||||||
@param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
|
|
||||||
must be between 0 and NumberOfTimers-1.
|
|
||||||
@param TimerValue Pointer to the returned timer value.
|
|
||||||
@param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
|
|
||||||
of TimerValue.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
|
|
||||||
@retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
|
|
||||||
@retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not have any readable timers.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
GetTimerValue (
|
|
||||||
IN UINT32 TimerIndex,
|
|
||||||
OUT UINT64 *TimerValue,
|
|
||||||
OUT UINT64 *TimerPeriod OPTIONAL
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (TimerValue == NULL) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TimerIndex == 0) {
|
|
||||||
*TimerValue = AsmReadTsc ();
|
|
||||||
if (TimerPeriod != NULL) {
|
|
||||||
//
|
|
||||||
// BugBug: Hard coded. Don't know how to do this generically
|
|
||||||
//
|
|
||||||
*TimerPeriod = 1000000000;
|
|
||||||
}
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function flushes the range of addresses from Start to Start+Length
|
|
||||||
from the processor's data cache. If Start is not aligned to a cache line
|
|
||||||
boundary, then the bytes before Start to the preceding cache line boundary
|
|
||||||
are also flushed. If Start+Length is not aligned to a cache line boundary,
|
|
||||||
then the bytes past Start+Length to the end of the next cache line boundary
|
|
||||||
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
|
|
||||||
supported. If the data cache is fully coherent with all DMA operations, then
|
|
||||||
this function can just return EFI_SUCCESS. If the processor does not support
|
|
||||||
flushing a range of the data cache, then the entire data cache can be flushed.
|
|
||||||
|
|
||||||
@param Start The beginning physical address to flush from the processor's data
|
|
||||||
cache.
|
|
||||||
@param Length The number of bytes to flush from the processor's data cache. This
|
|
||||||
function may flush more bytes than Length specifies depending upon
|
|
||||||
the granularity of the flush operation that the processor supports.
|
|
||||||
@param FlushType Specifies the type of flush operation to perform.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
|
|
||||||
the processor's data cache.
|
|
||||||
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
|
|
||||||
by FlushType.
|
|
||||||
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
|
|
||||||
from the processor's data cache.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
FlushCpuDataCache (
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Start,
|
|
||||||
IN UINT64 Length,
|
|
||||||
IN EFI_CPU_FLUSH_TYPE FlushType
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
|
|
||||||
AsmWbinvd ();
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
} else if (FlushType == EfiCpuFlushTypeInvalidate) {
|
|
||||||
AsmInvd ();
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
} else {
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
#/** @file
|
|
||||||
#
|
|
||||||
# Component discription file for Bds module
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008, Apple Inc. <BR>
|
|
||||||
# All rights reserved. This program and the accompanying materials
|
|
||||||
# are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
# which accompanies this distribution. The full text of the license may be found at
|
|
||||||
# http://opensource.org/licenses/bsd-license.php
|
|
||||||
#
|
|
||||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
#
|
|
||||||
#**/
|
|
||||||
|
|
||||||
[Defines]
|
|
||||||
INF_VERSION = 0x00010005
|
|
||||||
BASE_NAME = TemplateTimerDxe
|
|
||||||
FILE_GUID = E697928E-7C98-4501-8406-21F5509549CC
|
|
||||||
MODULE_TYPE = DXE_DRIVER
|
|
||||||
VERSION_STRING = 1.0
|
|
||||||
|
|
||||||
ENTRY_POINT = TimerInitialize
|
|
||||||
|
|
||||||
[Sources.common]
|
|
||||||
Timer.c
|
|
||||||
|
|
||||||
[Packages]
|
|
||||||
MdePkg/MdePkg.dec
|
|
||||||
EmbeddedPkg/EmbeddedPkg.dec
|
|
||||||
|
|
||||||
[LibraryClasses]
|
|
||||||
BaseLib
|
|
||||||
UefiRuntimeServicesTableLib
|
|
||||||
PerformanceLib
|
|
||||||
UefiLib
|
|
||||||
UefiBootServicesTableLib
|
|
||||||
BaseMemoryLib
|
|
||||||
DebugLib
|
|
||||||
UefiDriverEntryPoint
|
|
||||||
IoLib
|
|
||||||
|
|
||||||
[Guids]
|
|
||||||
|
|
||||||
[Protocols]
|
|
||||||
gEfiTimerArchProtocolGuid
|
|
||||||
gHardwareInterruptProtocolGuid
|
|
||||||
|
|
||||||
[Pcd.common]
|
|
||||||
gEmbeddedTokenSpaceGuid.PcdTimerBaseAddress
|
|
||||||
gEmbeddedTokenSpaceGuid.PcdTimerVector
|
|
||||||
gEmbeddedTokenSpaceGuid.PcdTimerPeriod
|
|
||||||
|
|
||||||
[Depex]
|
|
||||||
gHardwareInterruptProtocolGuid
|
|
@ -1,377 +0,0 @@
|
|||||||
/** @file
|
|
||||||
Template for Timer Architecture Protocol driver of the ARM flavor
|
|
||||||
|
|
||||||
Copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
|
||||||
|
|
||||||
All rights reserved. This program and the accompanying materials
|
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
|
||||||
http://opensource.org/licenses/bsd-license.php
|
|
||||||
|
|
||||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
#include <PiDxe.h>
|
|
||||||
|
|
||||||
#include <Library/BaseLib.h>
|
|
||||||
#include <Library/DebugLib.h>
|
|
||||||
#include <Library/BaseMemoryLib.h>
|
|
||||||
#include <Library/UefiBootServicesTableLib.h>
|
|
||||||
#include <Library/UefiLib.h>
|
|
||||||
#include <Library/PcdLib.h>
|
|
||||||
#include <Library/IoLib.h>
|
|
||||||
|
|
||||||
#include <Protocol/Timer.h>
|
|
||||||
#include <Protocol/HardwareInterrupt.h>
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get Base Address of timer block from platform .DSC file
|
|
||||||
//
|
|
||||||
#define TIMER_BASE ((UINTN)FixedPcdGet32 (PcdTimerBaseAddress) + 0x00c0)
|
|
||||||
|
|
||||||
|
|
||||||
#define TIMER_CMD ((UINTN)FixedPcdGet32 (PcdTimerBaseAddress) + 0x00000004)
|
|
||||||
#define TIMER_DATA ((UINTN)FixedPcdGet32 (PcdTimerBaseAddress) + 0x00000008)
|
|
||||||
|
|
||||||
//
|
|
||||||
// The notification function to call on every timer interrupt.
|
|
||||||
// A bug in the compiler prevents us from initializing this here.
|
|
||||||
//
|
|
||||||
volatile EFI_TIMER_NOTIFY mTimerNotifyFunction;
|
|
||||||
|
|
||||||
//
|
|
||||||
// The current period of the timer interrupt
|
|
||||||
//
|
|
||||||
volatile UINT64 mTimerPeriod = 0;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Cached copy of the Hardware Interrupt protocol instance
|
|
||||||
//
|
|
||||||
EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
C Interrupt Handler calledin the interrupt context when Source interrupt is active.
|
|
||||||
|
|
||||||
@param Source Source of the interrupt. Hardware routing off a specific platform defines
|
|
||||||
what source means.
|
|
||||||
@param SystemContext Pointer to system register context. Mostly used by debuggers and will
|
|
||||||
update the system context after the return from the interrupt if
|
|
||||||
modified. Don't change these values unless you know what you are doing
|
|
||||||
|
|
||||||
**/
|
|
||||||
VOID
|
|
||||||
EFIAPI
|
|
||||||
TimerInterruptHandler (
|
|
||||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
|
||||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_TPL OriginalTPL;
|
|
||||||
|
|
||||||
//
|
|
||||||
// DXE core uses this callback for the EFI timer tick. The DXE core uses locks
|
|
||||||
// that raise to TPL_HIGH and then restore back to current level. Thus we need
|
|
||||||
// to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
|
|
||||||
//
|
|
||||||
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
|
|
||||||
|
|
||||||
MmioWrite32 (TIMER_CMD, 0);
|
|
||||||
|
|
||||||
if (mTimerNotifyFunction) {
|
|
||||||
mTimerNotifyFunction (mTimerPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore state
|
|
||||||
gBS->RestoreTPL (OriginalTPL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function registers the handler NotifyFunction so it is called every time
|
|
||||||
the timer interrupt fires. It also passes the amount of time since the last
|
|
||||||
handler call to the NotifyFunction. If NotifyFunction is NULL, then the
|
|
||||||
handler is unregistered. If the handler is registered, then EFI_SUCCESS is
|
|
||||||
returned. If the CPU does not support registering a timer interrupt handler,
|
|
||||||
then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
|
|
||||||
when a handler is already registered, then EFI_ALREADY_STARTED is returned.
|
|
||||||
If an attempt is made to unregister a handler when a handler is not registered,
|
|
||||||
then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
|
|
||||||
register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
|
|
||||||
is returned.
|
|
||||||
|
|
||||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
|
||||||
@param NotifyFunction The function to call when a timer interrupt fires. This
|
|
||||||
function executes at TPL_HIGH_LEVEL. The DXE Core will
|
|
||||||
register a handler for the timer interrupt, so it can know
|
|
||||||
how much time has passed. This information is used to
|
|
||||||
signal timer based events. NULL will unregister the handler.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The timer handler was registered.
|
|
||||||
@retval EFI_UNSUPPORTED The platform does not support timer interrupts.
|
|
||||||
@retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
|
|
||||||
registered.
|
|
||||||
@retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
|
|
||||||
previously registered.
|
|
||||||
@retval EFI_DEVICE_ERROR The timer handler could not be registered.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
TimerDriverRegisterHandler (
|
|
||||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
|
||||||
IN EFI_TIMER_NOTIFY NotifyFunction
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Check for invalid parameters
|
|
||||||
//
|
|
||||||
if (NotifyFunction == NULL && mTimerNotifyFunction == NULL) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NotifyFunction != NULL && mTimerNotifyFunction != NULL) {
|
|
||||||
return EFI_ALREADY_STARTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
mTimerNotifyFunction = NotifyFunction;
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function adjusts the period of timer interrupts to the value specified
|
|
||||||
by TimerPeriod. If the timer period is updated, then the selected timer
|
|
||||||
period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
|
|
||||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
|
|
||||||
If an error occurs while attempting to update the timer period, then the
|
|
||||||
timer hardware will be put back in its state prior to this call, and
|
|
||||||
EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
|
|
||||||
is disabled. This is not the same as disabling the CPU's interrupts.
|
|
||||||
Instead, it must either turn off the timer hardware, or it must adjust the
|
|
||||||
interrupt controller so that a CPU interrupt is not generated when the timer
|
|
||||||
interrupt fires.
|
|
||||||
|
|
||||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
|
||||||
@param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
|
|
||||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is
|
|
||||||
returned. If the timer is programmable, then the timer period
|
|
||||||
will be rounded up to the nearest timer period that is supported
|
|
||||||
by the timer hardware. If TimerPeriod is set to 0, then the
|
|
||||||
timer interrupts will be disabled.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The timer period was changed.
|
|
||||||
@retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
|
|
||||||
@retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
TimerDriverSetTimerPeriod (
|
|
||||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
|
||||||
IN UINT64 TimerPeriod
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINT64 TimerCount;
|
|
||||||
|
|
||||||
if (TimerPeriod == 0) {
|
|
||||||
//
|
|
||||||
// Disable interrupt 0 and timer
|
|
||||||
//
|
|
||||||
MmioAnd32 (TIMER_DATA, 0);
|
|
||||||
|
|
||||||
Status = gInterrupt->DisableInterruptSource (gInterrupt, FixedPcdGet32 (PcdTimerVector));
|
|
||||||
} else {
|
|
||||||
//
|
|
||||||
// Convert TimerPeriod into Timer F counts
|
|
||||||
//
|
|
||||||
TimerCount = DivU64x32 (TimerPeriod + 5, 10);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Program Timer F with the new count value
|
|
||||||
//
|
|
||||||
MmioWrite32 (TIMER_DATA, (UINT32)TimerCount);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Enable interrupt and initialize and enable timer.
|
|
||||||
//
|
|
||||||
MmioOr32 (TIMER_CMD, 0x11);
|
|
||||||
|
|
||||||
Status = gInterrupt->EnableInterruptSource (gInterrupt, FixedPcdGet32 (PcdTimerVector));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Save the new timer period
|
|
||||||
//
|
|
||||||
mTimerPeriod = TimerPeriod;
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function retrieves the period of timer interrupts in 100 ns units,
|
|
||||||
returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
|
|
||||||
is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
|
|
||||||
returned, then the timer is currently disabled.
|
|
||||||
|
|
||||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
|
||||||
@param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
|
|
||||||
0 is returned, then the timer is currently disabled.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The timer period was returned in TimerPeriod.
|
|
||||||
@retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
TimerDriverGetTimerPeriod (
|
|
||||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
|
||||||
OUT UINT64 *TimerPeriod
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (TimerPeriod == NULL) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
*TimerPeriod = mTimerPeriod;
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function generates a soft timer interrupt. If the platform does not support soft
|
|
||||||
timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
|
|
||||||
If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
|
|
||||||
service, then a soft timer interrupt will be generated. If the timer interrupt is
|
|
||||||
enabled when this service is called, then the registered handler will be invoked. The
|
|
||||||
registered handler should not be able to distinguish a hardware-generated timer
|
|
||||||
interrupt from a software-generated timer interrupt.
|
|
||||||
|
|
||||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The soft timer interrupt was generated.
|
|
||||||
@retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
TimerDriverGenerateSoftInterrupt (
|
|
||||||
IN EFI_TIMER_ARCH_PROTOCOL *This
|
|
||||||
)
|
|
||||||
{
|
|
||||||
return EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Interface stucture for the Timer Architectural Protocol.
|
|
||||||
|
|
||||||
@par Protocol Description:
|
|
||||||
This protocol provides the services to initialize a periodic timer
|
|
||||||
interrupt, and to register a handler that is called each time the timer
|
|
||||||
interrupt fires. It may also provide a service to adjust the rate of the
|
|
||||||
periodic timer interrupt. When a timer interrupt occurs, the handler is
|
|
||||||
passed the amount of time that has passed since the previous timer
|
|
||||||
interrupt.
|
|
||||||
|
|
||||||
@param RegisterHandler
|
|
||||||
Registers a handler that will be called each time the
|
|
||||||
timer interrupt fires. TimerPeriod defines the minimum
|
|
||||||
time between timer interrupts, so TimerPeriod will also
|
|
||||||
be the minimum time between calls to the registered
|
|
||||||
handler.
|
|
||||||
|
|
||||||
@param SetTimerPeriod
|
|
||||||
Sets the period of the timer interrupt in 100 nS units.
|
|
||||||
This function is optional, and may return EFI_UNSUPPORTED.
|
|
||||||
If this function is supported, then the timer period will
|
|
||||||
be rounded up to the nearest supported timer period.
|
|
||||||
|
|
||||||
@param GetTimerPeriod
|
|
||||||
Retrieves the period of the timer interrupt in 100 nS units.
|
|
||||||
|
|
||||||
@param GenerateSoftInterrupt
|
|
||||||
Generates a soft timer interrupt that simulates the firing of
|
|
||||||
the timer interrupt. This service can be used to invoke the
|
|
||||||
registered handler if the timer interrupt has been masked for
|
|
||||||
a period of time.
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_TIMER_ARCH_PROTOCOL gTimer = {
|
|
||||||
TimerDriverRegisterHandler,
|
|
||||||
TimerDriverSetTimerPeriod,
|
|
||||||
TimerDriverGetTimerPeriod,
|
|
||||||
TimerDriverGenerateSoftInterrupt
|
|
||||||
};
|
|
||||||
|
|
||||||
EFI_HANDLE gTimerHandle = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Initialize the state information for the Timer Architectural Protocol
|
|
||||||
|
|
||||||
@param ImageHandle of the loaded driver
|
|
||||||
@param SystemTable Pointer to the System Table
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS Protocol registered
|
|
||||||
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
|
||||||
@retval EFI_DEVICE_ERROR Hardware problems
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
TimerInitialize (
|
|
||||||
IN EFI_HANDLE ImageHandle,
|
|
||||||
IN EFI_SYSTEM_TABLE *SystemTable
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Find the interrupt controller protocol. ASSERT if not found.
|
|
||||||
//
|
|
||||||
Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, ( VOID ** )&gInterrupt);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
MmioWrite32 (TIMER_CMD, 0x01);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Force the timer to be disabled
|
|
||||||
//
|
|
||||||
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Install interrupt handler
|
|
||||||
//
|
|
||||||
Status = gInterrupt->RegisterInterruptSource (gInterrupt, FixedPcdGet32 (PcdTimerVector), TimerInterruptHandler);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Force the timer to be enabled at its default period
|
|
||||||
//
|
|
||||||
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32 (PcdTimerPeriod));
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Install the Timer Architectural Protocol onto a new handle
|
|
||||||
//
|
|
||||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
||||||
&gTimerHandle,
|
|
||||||
&gEfiTimerArchProtocolGuid, &gTimer,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user