diff options
294 files changed, 47954 insertions, 0 deletions
diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec new file mode 100644 index 0000000000..9773f450e3 --- /dev/null +++ b/ArmPkg/ArmPkg.dec @@ -0,0 +1,36 @@ +#%HEADER%
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = ArmPkg
+ PACKAGE_GUID = 5CFBD99E-3C43-4E7F-8054-9CDEAFF7710F
+ PACKAGE_VERSION = 0.1
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+# Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+ Include # Root include for the package
+
+[LibraryClasses.common]
+ SemihostLib|Include/Library/Semihosting.h
+
+[Guids.common]
+ gArmTokenSpaceGuid = { 0xBB11ECFE, 0x820F, 0x4968, { 0xBB, 0xA6, 0xF7, 0x6A, 0xFE, 0x30, 0x25, 0x96 } }
+
+[Protocols.common]
+ gTimerDebugSupportProtocolGuid = { 0x68300561, 0x0197, 0x465d, { 0xb5, 0xa1, 0x28, 0xeb, 0xa1, 0x98, 0xdd, 0x0b } }
+
+[PcdsFeatureFlag.common]
+ gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport|FALSE|BOOLEAN|0x00000001
+
+[PcdsFixedAtBuild.common]
+ gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000080000000|UINT64|0x00000002
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold|1024|UINT32|0x00000003
+ gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0xfff00000|UINT32|0x00000004
+ gArmTokenSpaceGuid.PcdCpuResetAddress|0x00000000|UINT32|0x00000005
diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc new file mode 100644 index 0000000000..ca4f4fa555 --- /dev/null +++ b/ArmPkg/ArmPkg.dsc @@ -0,0 +1,61 @@ +#%HEADER% +#/** @file +# +# ARM Package +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = ArmPkg + PLATFORM_GUID = 5CFBD99E-3C43-4E7F-8054-9CDEAFF7710F + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/Arm + SUPPORTED_ARCHITECTURES = ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + + +[LibraryClasses.common] + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + + ArmLib|ArmPkg/Library/ArmLib/Null/NullArmLib.inf + SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf + UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf + + +[Components.common] + ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf + ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf + ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf + ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf + ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf + ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf + ArmPkg/Library/ArmLib/Null/NullArmLib.inf + ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf + ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf + ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf + ArmPkg/Library/SemihostLib/SemihostLib.inf + ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf + + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + ArmPkg/Filesystem/SemihostFs/SemihostFs.inf diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.c b/ArmPkg/Drivers/CpuDxe/CpuDxe.c new file mode 100644 index 0000000000..c57dac2f74 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.c @@ -0,0 +1,154 @@ +/** @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_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ switch (FlushType) {
+ case EfiCpuFlushTypeWriteBack:
+ WriteBackDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
+ break;
+ case EfiCpuFlushTypeInvalidate:
+ InvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
+ break;
+ case EfiCpuFlushTypeWriteBackInvalidate:
+ WriteBackInvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ if (ArmProcessorMode() != ARM_PROCESSOR_MODE_IRQ) {
+ ArmEnableInterrupts();
+ }
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ if (ArmProcessorMode() != ARM_PROCESSOR_MODE_IRQ) {
+ ArmDisableInterrupts();
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = ArmGetInterruptState();
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+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);
+}
+
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ 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
+};
+
+EFI_STATUS
+CpuDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ InitializeExceptions(&mCpu);
+ return gBS->InstallMultipleProtocolInterfaces(&mCpuHandle, &gEfiCpuArchProtocolGuid, &mCpu, NULL);
+}
+
diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.h b/ArmPkg/Drivers/CpuDxe/CpuDxe.h new file mode 100644 index 0000000000..36133e11c3 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.h @@ -0,0 +1,91 @@ +/** @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 __CPU_DXE_ARM_EXCEPTION_H__
+#define __CPU_DXE_ARM_EXCEPTION_H__
+
+#include <Uefi.h>
+
+#include <Library/ArmLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/DebugSupport.h>
+#include <Protocol/DebugSupportPeriodicCallback.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
+ );
+
+
+/**
+ 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
+RegisterDebuggerInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ );
+
+#endif // __CPU_DXE_ARM_EXCEPTION_H__
diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf new file mode 100644 index 0000000000..314965ca4a --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf @@ -0,0 +1,56 @@ +#%HEADER%
+#/** @file
+#
+# DXE CPU driver
+#
+# Copyright (c) 2009, 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 = ArmCpuDxe
+ FILE_GUID = B8D9777E-D72A-451F-9BDB-BAFB52A68415
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = CpuDxeInitialize
+
+[Sources.ARM]
+ CpuDxe.c
+ CpuDxe.h
+ DebugSupport.c
+ Exception.c
+ ExceptionSupport.asm | RVCT
+ ExceptionSupport.S | GCC
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ CacheMaintenanceLib
+ UefiDriverEntryPoint
+ ArmLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+ gEfiDebugSupportPeriodicCallbackProtocolGuid
+
+[Pcd.common]
+ gArmTokenSpaceGuid.PcdCpuVectorBaseAddress
+
+[FeaturePcd.common]
+ gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport
+
+[depex]
+ gHardwareInterruptProtocolGuid
diff --git a/ArmPkg/Drivers/CpuDxe/DebugSupport.c b/ArmPkg/Drivers/CpuDxe/DebugSupport.c new file mode 100644 index 0000000000..b8a5584939 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/DebugSupport.c @@ -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.
+
+**/
+/** @file
+ DXE Cpu Driver.
+
+ May need some porting work for platform specifics.
+
+ Copyright (c) 2008, Apple Inc
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CpuDxe.h"
+
+EFI_PERIODIC_CALLBACK gPeriodicCallBack = (EFI_PERIODIC_CALLBACK)NULL;
+
+EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL *gDebugSupportCallback = NULL;
+
+
+EFI_STATUS
+EFIAPI
+DebugSupportGetMaximumProcessorIndex (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ OUT UINTN *MaxProcessorIndex
+ )
+/*++
+
+Routine Description: This is a DebugSupport protocol member function.
+
+Arguments:
+ This - The DebugSupport instance
+ MaxProcessorIndex - The maximuim supported processor index
+
+Returns:
+ Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0
+
+--*/
+{
+ *MaxProcessorIndex = 0;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DebugSupportRegisterPeriodicCallback (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback
+ )
+/*++
+
+Routine Description: This is a DebugSupport protocol member function.
+
+Arguments:
+ This - The DebugSupport instance
+ ProcessorIndex - Which processor the callback applies to.
+ PeriodicCallback - Callback function
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has
+ no handler registered for it
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.
+
+ Other possible return values are passed through from UnHookEntry and HookEntry.
+
+--*/
+{
+ if (ProcessorIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((gPeriodicCallBack != (EFI_PERIODIC_CALLBACK)NULL) && (PeriodicCallback != (EFI_PERIODIC_CALLBACK)NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gPeriodicCallBack = PeriodicCallback;
+
+ if (gDebugSupportCallback != NULL) {
+ //
+ // We can only update this protocol if the Register Protocol Notify has fired. If it fires
+ // after this call it will update with gPeriodicCallBack value.
+ //
+ gDebugSupportCallback->PeriodicCallback = gPeriodicCallBack;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+DebugSupportRegisterExceptionCallback (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN EFI_EXCEPTION_CALLBACK NewCallback,
+ IN EFI_EXCEPTION_TYPE ExceptionType
+ )
+/*++
+
+Routine Description:
+ This is a DebugSupport protocol member function.
+
+ This code executes in boot services context.
+
+Arguments:
+ This - The DebugSupport instance
+ ProcessorIndex - Which processor the callback applies to.
+ NewCallback - Callback function
+ ExceptionType - Which exception to hook
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has
+ no handler registered for it
+ EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered.
+
+ Other possible return values are passed through from UnHookEntry and HookEntry.
+
+--*/
+{
+ if (ProcessorIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return RegisterDebuggerInterruptHandler (ExceptionType, NewCallback);
+}
+
+
+EFI_STATUS
+EFIAPI
+DebugSupportInvalidateInstructionCache (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN VOID *Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+ This is a DebugSupport protocol member function.
+ Calls assembly routine to flush cache.
+
+Arguments:
+ This - The DebugSupport instance
+ ProcessorIndex - Which processor the callback applies to.
+ Start - Physical base of the memory range to be invalidated
+ Length - mininum number of bytes in instruction cache to invalidate
+
+Returns:
+
+ EFI_SUCCESS - always return success
+
+--*/
+{
+ if (ProcessorIndex != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InvalidateInstructionCache();
+
+ return EFI_SUCCESS;
+}
+
+//
+// This is a global that is the actual interface
+//
+EFI_DEBUG_SUPPORT_PROTOCOL gDebugSupportProtocolInterface = {
+ IsaArm, // Fixme to be more generic
+ DebugSupportGetMaximumProcessorIndex,
+ DebugSupportRegisterPeriodicCallback,
+ DebugSupportRegisterExceptionCallback,
+ DebugSupportInvalidateInstructionCache
+};
+
+
+VOID
+EFIAPI
+DebugSupportPeriodicCallbackEventProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiDebugSupportPeriodicCallbackProtocolGuid, NULL, (VOID **)&gDebugSupportCallback);
+ if (!EFI_ERROR (Status)) {
+ gDebugSupportCallback->PeriodicCallback = gPeriodicCallBack;
+ }
+}
+
+VOID *gRegistration = NULL;
+
+
+EFI_DEBUG_SUPPORT_PROTOCOL *
+InitilaizeDebugSupport (
+ VOID
+ )
+{
+ // RPN gEfiDebugSupportPeriodicCallbackProtocolGuid
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ if (!FeaturePcdGet (PcdCpuDxeProduceDebugSupport)) {
+ // Don't include this code unless Feature Flag is set
+ return NULL;
+ }
+
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ DebugSupportPeriodicCallbackEventProtocolNotify,
+ NULL,
+ &Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->RegisterProtocolNotify (&gEfiDebugSupportPeriodicCallbackProtocolGuid, Event, &gRegistration);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // We assume the Timer must depend on our driver to register interrupts so we don't need to do
+ // a gBS->SignalEvent (Event) here to check to see if the protocol allready exists
+ //
+
+ return &gDebugSupportProtocolInterface;
+}
diff --git a/ArmPkg/Drivers/CpuDxe/Exception.c b/ArmPkg/Drivers/CpuDxe/Exception.c new file mode 100644 index 0000000000..fa256e60f8 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/Exception.c @@ -0,0 +1,238 @@ +/** @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];
+EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[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_ALREADY_STARTED;
+ }
+
+ gExceptionHandlers[InterruptType] = InterruptHandler;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ 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
+RegisterDebuggerInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType > MAX_ARM_EXCEPTION) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((InterruptHandler != NULL) && (gDebuggerExceptionHandlers[InterruptType] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gDebuggerExceptionHandlers[InterruptType] = InterruptHandler;
+
+ return EFI_SUCCESS;
+}
+
+
+
+VOID
+EFIAPI
+CommonCExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ BOOLEAN Dispatched = FALSE;
+
+ if (ExceptionType <= MAX_ARM_EXCEPTION) {
+ if (gDebuggerExceptionHandlers[ExceptionType]) {
+ //
+ // If DebugSupport hooked the interrupt call the handler. This does not disable
+ // the normal handler.
+ //
+ gDebuggerExceptionHandlers[ExceptionType] (ExceptionType, SystemContext);
+ Dispatched = TRUE;
+ }
+ if (gExceptionHandlers[ExceptionType]) {
+ gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext);
+ Dispatched = TRUE;
+ }
+ }
+
+ if (Dispatched) {
+ //
+ // We did work so this was an expected ExceptionType
+ //
+ return;
+ }
+
+ if (ExceptionType == EXCEPT_ARM_SOFTWARE_INTERRUPT) {
+ //
+ // ARM JTAG debuggers some times use this vector, so it is not an error to get one
+ //
+ return;
+ }
+
+ //
+ // Code after here is the default exception handler...
+ //
+ DEBUG ((EFI_D_ERROR, "Exception %d from %08x\n", ExceptionType, SystemContext.SystemContextArm->PC));
+ ASSERT (FALSE);
+
+}
+
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINTN Length;
+ UINTN Index;
+ BOOLEAN Enabled;
+ EFI_PHYSICAL_ADDRESS Base;
+
+ //
+ // Disable interrupts
+ //
+ Cpu->GetInterruptState (Cpu, &Enabled);
+ Cpu->DisableInterrupt (Cpu);
+
+ //
+ // Initialize the C entry points for interrupts
+ //
+ for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
+ Status = RegisterInterruptHandler (Index, NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = RegisterDebuggerInterruptHandler (Index, NULL);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Copy an implementation of the ARM exception vectors to 0x0.
+ //
+ Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
+
+ //
+ // Reserve space for the exception handlers
+ //
+ Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);
+ Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);
+ // If the request was for memory that's not in the memory map (which is often the case for 0x00000000
+ // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of
+ // EFI_NOT_FOUND, and continue in that case.
+ if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ 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
+ InvalidateInstructionCacheRange((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);
+
+ if (Enabled) {
+ //
+ // Restore interrupt state
+ //
+ Status = Cpu->EnableInterrupt (Cpu);
+ }
+
+ return Status;
+}
diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S new file mode 100755 index 0000000000..8574af6d71 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.S @@ -0,0 +1,152 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.align 3 + +.globl ASM_PFX(ExceptionHandlersStart) +.globl ASM_PFX(ExceptionHandlersEnd) +.globl ASM_PFX(CommonExceptionEntry) +.globl ASM_PFX(AsmCommonExceptionEntry) +.globl ASM_PFX(CommonCExceptionHandler) + +ASM_PFX(ExceptionHandlersStart): + +ASM_PFX(Reset): + b ASM_PFX(ResetEntry) + +ASM_PFX(UndefinedInstruction): + b ASM_PFX(UndefinedInstructionEntry) + +ASM_PFX(SoftwareInterrupt): + b ASM_PFX(SoftwareInterruptEntry) + +ASM_PFX(PrefetchAbort): + b ASM_PFX(PrefetchAbortEntry) + +ASM_PFX(DataAbort): + b ASM_PFX(DataAbortEntry) + +ASM_PFX(ReservedException): + b ASM_PFX(ReservedExceptionEntry) + +ASM_PFX(Irq): + b ASM_PFX(IrqEntry) + +ASM_PFX(Fiq): + b ASM_PFX(FiqEntry) + +ASM_PFX(ResetEntry): + stmfd sp!,{r0-r1} + mov r0,#0 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(UndefinedInstructionEntry): + stmfd sp!,{r0-r1} + mov r0,#1 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(SoftwareInterruptEntry): + stmfd sp!,{r0-r1} + mov r0,#2 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(PrefetchAbortEntry): + stmfd sp!,{r0-r1} + mov r0,#3 + sub lr,lr,#4 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(DataAbortEntry): + stmfd sp!,{r0-r1} + mov r0,#4 + sub lr,lr,#8 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(ReservedExceptionEntry): + stmfd sp!,{r0-r1} + mov r0,#5 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(IrqEntry): + stmfd sp!,{r0-r1} + mov r0,#6 + sub lr,lr,#4 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(FiqEntry): + stmfd sp!,{r0-r1} + mov r0,#7 + sub lr,lr,#4 + ldr r1,ASM_PFX(CommonExceptionEntry) + bx r1 + +ASM_PFX(CommonExceptionEntry): + .byte 0x12 + .byte 0x34 + .byte 0x56 + .byte 0x78 + +ASM_PFX(ExceptionHandlersEnd): + +ASM_PFX(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,#0x50] @ Read saved R1 from the stack (it was saved by the exception entry routine) + ldr r2,[sp,#0x4C] @ 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 + + sub sp,sp,#4 @ Adjust SP to preserve 8-byte alignment + bl ASM_PFX(CommonCExceptionHandler) @ Call exception handler + add sp,sp,#4 @ Adjust SP back to where we were + + 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 + diff --git a/ArmPkg/Drivers/CpuDxe/ExceptionSupport.asm b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.asm new file mode 100755 index 0000000000..d91720cff3 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/ExceptionSupport.asm @@ -0,0 +1,152 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + EXPORT ExceptionHandlersStart + EXPORT ExceptionHandlersEnd + EXPORT CommonExceptionEntry + EXPORT AsmCommonExceptionEntry + IMPORT CommonCExceptionHandler + + PRESERVE8 + 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,#0x50] ; Read saved R1 from the stack (it was saved by the exception entry routine) + ldr R2,[SP,#0x4C] ; 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 + + sub SP,SP,#4 ; Adjust SP to preserve 8-byte alignment + blx CommonCExceptionHandler ; Call exception handler + add SP,SP,#4 ; Adjust SP back to where we were + + 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 + + diff --git a/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c b/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c new file mode 100644 index 0000000000..26f4c387dc --- /dev/null +++ b/ArmPkg/Drivers/DebugSupportDxe/DebugSupport.c @@ -0,0 +1,119 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/DebugSupport.h>
+#include <Protocol/TimerDebugSupport.h>
+
+EFI_STATUS
+EFIAPI
+DebugSupportGetMaximumProcessorIndex (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ OUT UINTN *MaxProcessorIndex
+ )
+{
+ if (MaxProcessorIndex == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *MaxProcessorIndex = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DebugSupportRegisterPeriodicCallback (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback
+ )
+{
+ TIMER_DEBUG_SUPPORT_PROTOCOL *Timer;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol(&gTimerDebugSupportProtocolGuid, NULL, (VOID **)&Timer);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = Timer->RegisterPeriodicCallback(Timer, PeriodicCallback);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DebugSupportRegisterExceptionCallback (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN EFI_EXCEPTION_CALLBACK ExceptionCallback,
+ IN EFI_EXCEPTION_TYPE ExceptionType
+ )
+{
+ EFI_CPU_ARCH_PROTOCOL *Cpu;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = Cpu->RegisterInterruptHandler(Cpu, ExceptionType, (EFI_CPU_INTERRUPT_HANDLER)ExceptionCallback);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DebugSupportInvalidateInstructionCache (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN VOID *Start,
+ IN UINT64 Length
+ )
+{
+ InvalidateInstructionCacheRange(Start, Length);
+ return EFI_SUCCESS;
+}
+
+EFI_DEBUG_SUPPORT_PROTOCOL mDebugSupport = {
+ IsaArm,
+ DebugSupportGetMaximumProcessorIndex,
+ DebugSupportRegisterPeriodicCallback,
+ DebugSupportRegisterExceptionCallback,
+ DebugSupportInvalidateInstructionCache
+};
+
+EFI_STATUS
+DebugSupportDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = NULL;
+
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiDebugSupportProtocolGuid);
+ Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiDebugSupportProtocolGuid, &mDebugSupport, NULL);
+
+ return Status;
+}
+
diff --git a/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf b/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf new file mode 100644 index 0000000000..59f44879c4 --- /dev/null +++ b/ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf @@ -0,0 +1,30 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmDebugSupportDxe
+ FILE_GUID = 2e7c151b-cbd8-4df6-a0e3-cde660067c6a
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = DebugSupportDxeInitialize
+
+[Sources.common]
+ DebugSupport.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ CacheMaintenanceLib
+ UefiDriverEntryPoint
+ ArmLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+ gEfiDebugSupportProtocolGuid
+ gTimerDebugSupportProtocolGuid
+
+[Depex]
+ TRUE
\ No newline at end of file diff --git a/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c new file mode 100644 index 0000000000..0f1da65ba0 --- /dev/null +++ b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c @@ -0,0 +1,526 @@ +/** @file
+ Support a Semi Host file system over a debuggers JTAG
+
+ 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 <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SemihostLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include "SemihostFs.h"
+
+
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gSemihostFs = {
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
+ VolumeOpen
+};
+
+EFI_FILE gSemihostFsFile = {
+ EFI_FILE_PROTOCOL_REVISION,
+ FileOpen,
+ FileClose,
+ FileDelete,
+ FileRead,
+ FileWrite,
+ FileGetPosition,
+ FileSetPosition,
+ FileGetInfo,
+ FileSetInfo,
+ FileFlush
+};
+
+//
+// Device path for SemiHosting. It contains our autogened Caller ID GUID.
+//
+typedef struct {
+ VENDOR_DEVICE_PATH Guid;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} SEMIHOST_DEVICE_PATH;
+
+SEMIHOST_DEVICE_PATH gDevicePath = {
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0 },
+ EFI_CALLER_ID_GUID
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
+};
+
+typedef struct {
+ LIST_ENTRY Link;
+ UINT64 Signature;
+ EFI_FILE File;
+ CHAR8 *FileName;
+ UINT32 Position;
+ UINT32 SemihostHandle;
+ BOOLEAN IsRoot;
+} SEMIHOST_FCB;
+
+#define SEMIHOST_FCB_SIGNATURE SIGNATURE_32( 'S', 'H', 'F', 'C' )
+#define SEMIHOST_FCB_FROM_THIS(a) CR(a, SEMIHOST_FCB, File, SEMIHOST_FCB_SIGNATURE)
+#define SEMIHOST_FCB_FROM_LINK(a) CR(a, SEMIHOST_FCB, Link, SEMIHOST_FCB_SIGNATURE);
+
+EFI_HANDLE gInstallHandle = NULL;
+LIST_ENTRY gFileList = INITIALIZE_LIST_HEAD_VARIABLE (gFileList);
+
+SEMIHOST_FCB *
+AllocateFCB (
+ VOID
+ )
+{
+ SEMIHOST_FCB *Fcb = AllocateZeroPool (sizeof (SEMIHOST_FCB));
+
+ if (Fcb != NULL) {
+ CopyMem (&Fcb->File, &gSemihostFsFile, sizeof (gSemihostFsFile));
+ Fcb->Signature = SEMIHOST_FCB_SIGNATURE;
+ }
+
+ return Fcb;
+}
+
+VOID
+FreeFCB (
+ IN SEMIHOST_FCB *Fcb
+ )
+{
+ // Remove Fcb from gFileList.
+ RemoveEntryList (&Fcb->Link);
+
+ // To help debugging...
+ Fcb->Signature = 0;
+
+ FreePool (Fcb);
+}
+
+
+
+EFI_STATUS
+VolumeOpen (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE **Root
+ )
+{
+ SEMIHOST_FCB *RootFcb = NULL;
+
+ if (Root == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RootFcb = AllocateFCB ();
+ if (RootFcb == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RootFcb->IsRoot = TRUE;
+
+ InsertTailList (&gFileList, &RootFcb->Link);
+
+ *Root = &RootFcb->File;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FileOpen (
+ IN EFI_FILE *File,
+ OUT EFI_FILE **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ SEMIHOST_FCB *FileFcb = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINT32 SemihostHandle;
+ CHAR8 *AsciiFileName;
+ CHAR8 *AsciiPtr;
+ UINTN Length;
+ UINT32 SemihostMode;
+ BOOLEAN IsRoot;
+
+ if ((FileName == NULL) || (NewHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Semihost interface requires ASCII filesnames
+ Length = StrSize (FileName);
+
+ AsciiFileName = AllocatePool (Length);
+ if (AsciiFileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AsciiPtr = AsciiFileName;
+
+ while (Length--) {
+ *AsciiPtr++ = *FileName++ & 0xFF;
+ }
+
+ if ((AsciiStrCmp (AsciiFileName, "\\") == 0) || (AsciiStrCmp (AsciiFileName, "/") == 0) || (AsciiStrCmp (AsciiFileName, "") == 0)) {
+ // Opening '/', '\', or the NULL pathname is trying to open the root directory
+ IsRoot = TRUE;
+
+ // Root directory node doesn't have a name.
+ FreePool (AsciiFileName);
+ AsciiFileName = NULL;
+ } else {
+ // Translate EFI_FILE_MODE into Semihosting mode
+ if (OpenMode & EFI_FILE_MODE_WRITE) {
+ SemihostMode = SEMIHOST_FILE_MODE_WRITE | SEMIHOST_FILE_MODE_BINARY;
+ } else if (OpenMode & EFI_FILE_MODE_READ) {
+ SemihostMode = SEMIHOST_FILE_MODE_READ | SEMIHOST_FILE_MODE_BINARY;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ // Add the creation flag if necessary
+ if (OpenMode & EFI_FILE_MODE_CREATE) {
+ SemihostMode |= SEMIHOST_FILE_MODE_CREATE;
+ }
+
+ // Call the semihosting interface to open the file.
+ Status = SemihostFileOpen (AsciiFileName, SemihostMode, &SemihostHandle);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ IsRoot = FALSE;
+ }
+
+ // Allocate a control block and fill it
+ FileFcb = AllocateFCB ();
+ if (FileFcb == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileFcb->FileName = AsciiFileName;
+ FileFcb->SemihostHandle = SemihostHandle;
+ FileFcb->Position = 0;
+ FileFcb->IsRoot = IsRoot;
+
+ InsertTailList (&gFileList, &FileFcb->Link);
+
+ *NewHandle = &FileFcb->File;
+
+ return Status;
+}
+
+
+EFI_STATUS
+FileClose (
+ IN EFI_FILE *File
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ if (Fcb->IsRoot == TRUE) {
+ FreeFCB (Fcb);
+ Status = EFI_SUCCESS;
+ } else {
+ Status = SemihostFileClose (Fcb->SemihostHandle);
+ if (!EFI_ERROR(Status)) {
+ FreePool (Fcb->FileName);
+ FreeFCB (Fcb);
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FileDelete (
+ IN EFI_FILE *File
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status;
+ CHAR8 *FileName;
+ UINTN NameSize;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ // Get the filename from the Fcb
+ NameSize = AsciiStrLen (Fcb->FileName);
+ FileName = AllocatePool (NameSize + 1);
+
+ AsciiStrCpy (FileName, Fcb->FileName);
+
+ // Close the file if it's open. Disregard return status,
+ // since it might give an error if the file isn't open.
+ File->Close (File);
+
+ // Call the semihost interface to delete the file.
+ Status = SemihostFileRemove (FileName);
+
+ return Status;
+}
+
+EFI_STATUS
+FileRead (
+ IN EFI_FILE *File,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ if (Fcb->IsRoot == TRUE) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ Status = SemihostFileRead (Fcb->SemihostHandle, BufferSize, Buffer);
+ if (!EFI_ERROR (Status)) {
+ Fcb->Position += *BufferSize;
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FileWrite (
+ IN EFI_FILE *File,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status;
+ UINTN WriteSize = *BufferSize;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ Status = SemihostFileWrite (Fcb->SemihostHandle, &WriteSize, Buffer);
+
+ if (!EFI_ERROR(Status)) {
+ // Semihost write return the number of bytes *NOT* written.
+ *BufferSize -= WriteSize;
+ Fcb->Position += *BufferSize;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FileGetPosition (
+ IN EFI_FILE *File,
+ OUT UINT64 *Position
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+
+ if (Position == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ *Position = Fcb->Position;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FileSetPosition (
+ IN EFI_FILE *File,
+ IN UINT64 Position
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ UINT32 Length;
+ EFI_STATUS Status;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ Status = SemihostFileLength (Fcb->SemihostHandle, &Length);
+ if (!EFI_ERROR(Status) && (Length < Position)) {
+ Position = Length;
+ }
+
+ Status = SemihostFileSeek (Fcb->SemihostHandle, (UINT32)Position);
+ if (!EFI_ERROR(Status)) {
+ Fcb->Position = Position;
+ }
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+GetFileInfo (
+ IN SEMIHOST_FCB *Fcb,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_FILE_INFO *Info = NULL;
+ UINTN NameSize = 0;
+ UINTN ResultSize;
+ UINTN Index;
+ UINT32 Length;
+ EFI_STATUS Status;
+
+ if (Fcb->IsRoot == TRUE) {
+ ResultSize = SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);
+ } else {
+ NameSize = AsciiStrLen (Fcb->FileName) + 1;
+ ResultSize = SIZE_OF_EFI_FILE_INFO + NameSize * sizeof (CHAR16);
+ }
+
+ if (*BufferSize < ResultSize) {
+ *BufferSize = ResultSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Info = Buffer;
+
+ // Zero out the structure
+ ZeroMem (Info, SIZE_OF_EFI_FILE_INFO);
+
+ // Fill in the structure
+ Info->Size = ResultSize;
+
+ if (Fcb->IsRoot == TRUE) {
+ Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;
+ Info->FileName[0] = L'\0';
+ } else {
+ Status = SemihostFileLength (Fcb->SemihostHandle, &Length);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Info->FileSize = Length;
+ Info->PhysicalSize = Length;
+
+ for (Index = 0; Index < NameSize; Index++) {
+ Info->FileName[Index] = Fcb->FileName[Index];
+ }
+ }
+
+
+ *BufferSize = ResultSize;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+GetFilesystemInfo (
+ IN SEMIHOST_FCB *Fcb,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_FILE_SYSTEM_INFO *Info = NULL;
+ EFI_STATUS Status;
+ STATIC CHAR16 Label[] = L"SemihostFs";
+ UINTN ResultSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(Label);
+
+ if(*BufferSize >= ResultSize) {
+ ZeroMem (Buffer, ResultSize);
+ Status = EFI_SUCCESS;
+
+ Info = Buffer;
+
+ Info->Size = ResultSize;
+ Info->ReadOnly = FALSE;
+ Info->VolumeSize = 0;
+ Info->FreeSpace = 0;
+ Info->BlockSize = 0;
+
+ StrCpy (Info->VolumeLabel, Label);
+ } else {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *BufferSize = ResultSize;
+ return Status;
+}
+
+EFI_STATUS
+FileGetInfo (
+ IN EFI_FILE *File,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ SEMIHOST_FCB *Fcb = NULL;
+ EFI_STATUS Status = EFI_UNSUPPORTED;
+
+ Fcb = SEMIHOST_FCB_FROM_THIS(File);
+
+ if (CompareGuid(InformationType, &gEfiFileSystemInfoGuid) != 0) {
+ Status = GetFilesystemInfo(Fcb, BufferSize, Buffer);
+ } else if (CompareGuid(InformationType, &gEfiFileInfoGuid) != 0) {
+ Status = GetFileInfo(Fcb, BufferSize, Buffer);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FileSetInfo (
+ IN EFI_FILE *File,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+FileFlush (
+ IN EFI_FILE *File
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SemihostFsEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status = EFI_NOT_FOUND;
+
+ if (SemihostConnectionSupported ()) {
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gInstallHandle,
+ &gEfiSimpleFileSystemProtocolGuid, &gSemihostFs,
+ &gEfiDevicePathProtocolGuid, &gDevicePath,
+ NULL
+ );
+ }
+
+ return Status;
+}
+
diff --git a/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h new file mode 100644 index 0000000000..f058d92e29 --- /dev/null +++ b/ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h @@ -0,0 +1,114 @@ +/** @file
+ Support a Semi Host file system over a debuggers JTAG
+
+ 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 __SEMIHOST_FS_H__
+#define __SEMIHOST_FS_H__
+
+EFI_STATUS
+SemihostFsSupported(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+SemihostFsStart(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+SemihostFsStop(
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+EFI_STATUS
+VolumeOpen(
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE **Root
+ );
+
+EFI_STATUS
+FileOpen(
+ IN EFI_FILE *File,
+ OUT EFI_FILE **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS
+FileClose(
+ IN EFI_FILE *File
+ );
+
+EFI_STATUS
+FileDelete(
+ IN EFI_FILE *File
+ );
+
+EFI_STATUS
+FileRead(
+ IN EFI_FILE *File,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+FileWrite(
+ IN EFI_FILE *File,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ );
+
+EFI_STATUS
+FileGetPosition(
+ IN EFI_FILE *File,
+ OUT UINT64 *Position
+ );
+
+EFI_STATUS
+FileSetPosition(
+ IN EFI_FILE *File,
+ IN UINT64 Position
+ );
+
+EFI_STATUS
+FileGetInfo(
+ IN EFI_FILE *File,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+FileSetInfo(
+ IN EFI_FILE *File,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+EFI_STATUS
+FileFlush(
+ IN EFI_FILE *File
+ );
+
+#endif // __SEMIHOST_FS_H__
+
diff --git a/ArmPkg/Filesystem/SemihostFs/SemihostFs.inf b/ArmPkg/Filesystem/SemihostFs/SemihostFs.inf new file mode 100644 index 0000000000..7fca293d6f --- /dev/null +++ b/ArmPkg/Filesystem/SemihostFs/SemihostFs.inf @@ -0,0 +1,48 @@ +#%HEADER% +#/** @file +# Support a Semi Host file system over a debuggers JTAG +# +# Copyright (c) 2009, Apple, Inc. +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SemihostFs + FILE_GUID = C5B9C74A-6D72-4719-99AB-C59F199091EB + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = SemihostFsEntryPoint + + +[Sources.ARM] + Arm/SemihostFs.c + +[Packages] + MdePkg/MdePkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseLib + MemoryAllocationLib + SemihostLib + UefiDriverEntryPoint + UefiLib + +[Guids] + gEfiFileSystemInfoGuid + gEfiFileInfoGuid + gEfiFileSystemVolumeLabelInfoIdGuid + +[Protocols] + gEfiSimpleFileSystemProtocolGuid + gEfiDevicePathProtocolGuid + diff --git a/ArmPkg/Include/AsmMacroIoLib.h b/ArmPkg/Include/AsmMacroIoLib.h new file mode 100644 index 0000000000..aa3ed61632 --- /dev/null +++ b/ArmPkg/Include/AsmMacroIoLib.h @@ -0,0 +1,236 @@ +/** @file
+ Macros to work around lack of Apple support for LDR register, =expr
+
+ 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 __MACRO_IO_LIB_H__
+#define __MACRO_IO_LIB_H__
+
+#if defined(__APPLE__)
+
+//
+// ldr reg, =expr does not work with current Apple tool chain. So do the work our selves
+//
+
+// returns _Data in R0 and _Address in R1
+#define MmioWrite32(_Address, _Data) \
+ ldr r1, [pc, #8] ; \
+ ldr r0, [pc, #8] ; \
+ str r0, [r1] ; \
+ b 1f ; \
+ .long (_Address) ; \
+ .long (_Data) ; \
+1:
+
+// returns _Data in R0 and _Address in R1, and _OrData in r2
+#define MmioOr32(_Address, _OrData) \
+ ldr r1, [pc, #16] ; \
+ ldr r2, [pc, #16] ; \
+ ldr r0, [r1] ; \
+ orr r0, r0, r2 ; \
+ str r0, [r1] ; \
+ b 1f ; \
+ .long (_Address) ; \
+ .long (_OrData) ; \
+1:
+
+// returns _Data in R0 and _Address in R1, and _OrData in r2
+#define MmioAnd32(_Address, _AndData) \
+ ldr r1, [pc, #16] ; \
+ ldr r2, [pc, #16] ; \
+ ldr r0, [r1] ; \
+ and r0, r0, r2 ; \
+ str r0, [r1] ; \
+ b 1f ; \
+ .long (_Address) ; \
+ .long (_AndData) ; \
+1:
+
+// returns result in R0, _Address in R1, and _OrData in r2
+#define MmioAndThenOr32(_Address, _AndData, _OrData) \
+ ldr r1, [pc, #24] ; \
+ ldr r0, [r1] ; \
+ ldr r2, [pc, #20] ; \
+ and r0, r0, r2 ; \
+ ldr r2, [pc, #16] ; \
+ orr r0, r0, r2 ; \
+ str r0, [r1] ; \
+ b 1f ; \
+ .long (_Address) ; \
+ .long (_AndData) ; \
+ .long (_OrData) ; \
+1:
+
+// returns _Data in _Reg and _Address in R1
+#define MmioWriteFromReg32(_Address, _Reg) \
+ ldr r1, [pc, #4] ; \
+ str _Reg, [r1] ; \
+ b 1f ; \
+ .long (_Address) ; \
+1:
+
+
+// returns _Data in R0 and _Address in R1
+#define MmioRead32(_Address) \
+ ldr r1, [pc, #4] ; \
+ ldr r0, [r1] ; \
+ b 1f ; \
+ .long (_Address) ; \
+1:
+
+// returns _Data in Reg and _Address in R1
+#define MmioReadToReg32(_Address, _Reg) \
+ ldr r1, [pc, #4] ; \
+ ldr _Reg, [r1] ; \
+ b 1f ; \
+ .long (_Address) ; \
+1:
+
+
+// load R0 with _Data
+#define LoadConstant(_Data) \
+ ldr r0, [pc, #0] ; \
+ b 1f ; \
+ .long (_Data) ; \
+1:
+
+// load _Reg with _Data
+#define LoadConstantToReg(_Data, _Reg) \
+ ldr _Reg, [pc, #0] ; \
+ b 1f ; \
+ .long (_Data) ; \
+1:
+
+// load _Reg with _Data if eq
+#define LoadConstantToRegIfEq(_Data, _Reg) \
+ ldreq _Reg, [pc, #0] ; \
+ b 1f ; \
+ .long (_Data) ; \
+1:
+
+
+#elif defined (__GNUC__)
+
+#define MmioWrite32(Address, Data) \
+ ldr r1, =Address ; \
+ ldr r0, =Data ; \
+ str r0, [r1]
+
+#define MmioOr32(Address, OrData) \
+ ldr r1, =Address ; \
+ ldr r2, =OrData ; \
+ ldr r0, [r1] ; \
+ orr r0, r0, r2 ; \
+ str r0, [r1]
+
+#define MmioAnd32(Address, AndData) \
+ ldr r1, =Address ; \
+ ldr r2, =AndData ; \
+ ldr r0, [r1] ; \
+ and r0, r0, r2 ; \
+ str r0, [r1]
+
+#define MmioAndThenOr32(Address, AndData, OrData) \
+ ldr r1, =Address ; \
+ ldr r0, [r1] ; \
+ ldr r2, =AndData ; \
+ and r0, r0, r2 ; \
+ ldr r2, =OrData ; \
+ orr r0, r0, r2 ; \
+ str r0, [r1]
+
+#define MmioWriteFromReg32(Address, Reg) \
+ ldr r1, =Address ; \
+ str Reg, [r1]
+
+#define MmioRead32(Address) \
+ ldr r1, =Address ; \
+ ldr r0, [r1]
+
+#define MmioReadToReg32(Address, Reg) \
+ ldr r1, =Address ; \
+ ldr Reg, [r1]
+
+#define LoadConstant(Data) \
+ ldr r0, =Data
+
+#define LoadConstantToReg(Data, Reg) \
+ ldr Reg, =Data
+
+#else
+
+//
+// Use ARM assembly macros, form armasam
+//
+// Less magic in the macros if ldr reg, =expr works
+//
+
+// returns _Data in R0 and _Address in R1
+
+
+
+#define MmioWrite32(Address, Data) MmioWrite32Macro Address, Data
+
+
+
+
+// returns Data in R0 and Address in R1, and OrData in r2
+#define MmioOr32(Address, OrData) MmioOr32Macro Address, OrData
+
+
+// returns _Data in R0 and _Address in R1, and _OrData in r2
+
+
+#define MmioAnd32(Address, AndData) MmioAnd32Macro Address, AndData
+
+// returns result in R0, _Address in R1, and _OrData in r2
+
+
+#define MmioAndThenOr32(Address, AndData, OrData) MmioAndThenOr32Macro Address, AndData, OrData
+
+
+// returns _Data in _Reg and _Address in R1
+
+
+#define MmioWriteFromReg32(Address, Reg) MmioWriteFromReg32Macro Address, Reg
+
+// returns _Data in R0 and _Address in R1
+
+
+#define MmioRead32(Address) MmioRead32Macro Address
+
+// returns _Data in Reg and _Address in R1
+
+
+#define MmioReadToReg32(Address, Reg) MmioReadToReg32Macro Address, Reg
+
+
+// load R0 with _Data
+
+
+#define LoadConstant(Data) LoadConstantMacro Data
+
+// load _Reg with _Data
+
+
+#define LoadConstantToReg(Data, Reg) LoadConstantToRegMacro Data, Reg
+
+// conditional load testing eq flag
+#define LoadConstantToRegIfEq(Data, Reg) LoadConstantToRegIfEqMacro Data, Reg
+
+
+#endif
+
+
+#endif
diff --git a/ArmPkg/Include/AsmMacroIoLib.inc b/ArmPkg/Include/AsmMacroIoLib.inc new file mode 100644 index 0000000000..23f3c44d6b --- /dev/null +++ b/ArmPkg/Include/AsmMacroIoLib.inc @@ -0,0 +1,74 @@ +;%HEADER%
+;/** @file
+; Macros to work around lack of Apple support for LDR register, =expr
+;
+; Copyright (c) 2009, Apple, Inc. All rights reserved.
+;
+;**/
+
+
+ MACRO
+ MmioWrite32Macro $Address, $Data
+ ldr r1, = ($Address)
+ ldr r0, = ($Data)
+ str r0, [r1]
+ MEND
+
+ MACRO
+ MmioOr32Macro $Address, $OrData
+ ldr r1, =($Address)
+ ldr r2, =($OrData)
+ ldr r0, [r1]
+ orr r0, r0, r2
+ str r0, [r1]
+ MEND
+
+ MACRO
+ MmioAnd32Macro $Address, $AndData
+ ldr r1, =($Address)
+ ldr r2, =($AndData)
+ ldr r0, [r1]
+ and r0, r0, r2
+ str r0, [r1]
+ MEND
+
+ MACRO
+ MmioAndThenOr32Macro $Address, $AndData, $OrData
+ ldr r1, =($Address)
+ ldr r0, [r1]
+ ldr r2, =($AndData)
+ and r0, r0, r2
+ ldr r2, =($OrData)
+ orr r0, r0, r2
+ str r0, [r1]
+ MEND
+
+ MACRO
+ MmioWriteFromReg32Macro $Address, $Reg
+ ldr r1, =($Address)
+ str $Reg, [r1]
+ MEND
+
+ MACRO
+ MmioRead32Macro $Address
+ ldr r1, =($Address)
+ ldr r0, [r1]
+ MEND
+
+ MACRO
+ MmioReadToReg32Macro $Address, $Reg
+ ldr r1, =($Address)
+ ldr $Reg, [r1]
+ MEND
+
+ MACRO
+ LoadConstantMacro $Data
+ ldr r0, =($Data)
+ MEND
+
+ MACRO
+ LoadConstantToRegMacro $Data, $Reg
+ ldr $Reg, =($Data)
+ MEND
+
+ END
diff --git a/ArmPkg/Include/Chipset/ARM1176JZ-S.h b/ArmPkg/Include/Chipset/ARM1176JZ-S.h new file mode 100644 index 0000000000..2331f8effc --- /dev/null +++ b/ArmPkg/Include/Chipset/ARM1176JZ-S.h @@ -0,0 +1,111 @@ +/** @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 __ARM1176JZ_S_H__
+#define __ARM1176JZ_S_H__
+
+// Domain Access Control Register
+#define DOMAIN_ACCESS_CONTROL_MASK(a) (3UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_NONE(a) (0UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_CLIENT(a) (1UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_RESERVED(a) (2UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_MANAGER(a) (3UL << (2 * (a)))
+
+#define TRANSLATION_TABLE_SIZE (16 * 1024)
+#define TRANSLATION_TABLE_ALIGNMENT (16 * 1024)
+#define TRANSLATION_TABLE_ALIGNMENT_MASK (TRANSLATION_TABLE_ALIGNMENT - 1)
+
+#define TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(table, address) ((UINT32 *)(table) + (((UINTN)(address)) >> 20))
+
+// Translation table descriptor types
+#define TT_DESCRIPTOR_TYPE_MASK ((1UL << 18) | (3UL << 0))
+#define TT_DESCRIPTOR_TYPE_PAGE_TABLE ((0UL << 18) | (1UL << 0))
+#define TT_DESCRIPTOR_TYPE_SECTION ((0UL << 18) | (2UL << 0))
+#define TT_DESCRIPTOR_TYPE_SUPERSECTION ((1UL << 18) | (2UL << 0))
+
+// Section descriptor definitions
+#define TT_DESCRIPTOR_SECTION_SIZE (0x00100000)
+
+#define TT_DESCRIPTOR_SECTION_NS_MASK (1UL << 19)
+#define TT_DESCRIPTOR_SECTION_NS_SECURE (0UL << 19)
+#define TT_DESCRIPTOR_SECTION_NS_NON_SECURE (1UL << 19)
+
+#define TT_DESCRIPTOR_SECTION_NG_MASK (1UL << 17)
+#define TT_DESCRIPTOR_SECTION_NG_GLOBAL (0UL << 17)
+#define TT_DESCRIPTOR_SECTION_NG_LOCAL (1UL << 17)
+
+#define TT_DESCRIPTOR_SECTION_S_MASK (1UL << 16)
+#define TT_DESCRIPTOR_SECTION_S_NOT_SHARED (0UL << 16)
+#define TT_DESCRIPTOR_SECTION_S_SHARED (1UL << 16)
+
+#define TT_DESCRIPTOR_SECTION_AP_MASK ((1UL << 15) | (3UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_NO_NO ((0UL << 15) | (0UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RW_NO ((0UL << 15) | (1UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RW_RO ((0UL << 15) | (2UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RW_RW ((0UL << 15) | (3UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RO_NO ((1UL << 15) | (1UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RO_RO ((1UL << 15) | (3UL << 10))
+
+#define TT_DESCRIPTOR_CACHE_POLICY_NON_CACHEABLE (0UL)
+#define TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_ALLOCATE (1UL)
+#define TT_DESCRIPTOR_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE (2UL)
+#define TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE (3UL)
+
+#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_MASK ((1UL << 14) | (3UL << 12))
+#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_NON_CACHEABLE ((1UL << 14) | (TT_DESCRIPTOR_CACHE_POLICY_NON_CACHEABLE << 12))
+#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_BACK_ALLOCATE ((1UL << 14) | (TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_ALLOCATE << 12))
+#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE ((1UL << 14) | (TT_DESCRIPTOR_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE << 12))
+#define TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE ((1UL << 14) | (TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE << 12))
+
+#define TT_DESCRIPTOR_INNER_CACHE_POLICY_MASK (3UL << 2)
+#define TT_DESCRIPTOR_INNER_CACHE_POLICY_NON_CACHEABLE (TT_DESCRIPTOR_CACHE_POLICY_NON_CACHEABLE << 2)
+#define TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_BACK_ALLOCATE (TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_ALLOCATE << 2)
+#define TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE (TT_DESCRIPTOR_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE << 2)
+#define TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE (TT_DESCRIPTOR_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE << 2)
+
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK (TT_DESCRIPTOR_OUTER_CACHE_POLICY_MASK | TT_DESCRIPTOR_INNER_CACHE_POLICY_MASK)
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC (TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE | TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_THROUGH_NO_ALLOCATE)
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC (TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE | TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_BACK_NO_ALLOCATE)
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE (TT_DESCRIPTOR_OUTER_CACHE_POLICY_NON_CACHEABLE | TT_DESCRIPTOR_INNER_CACHE_POLICY_NON_CACHEABLE)
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC (TT_DESCRIPTOR_OUTER_CACHE_POLICY_WRITE_BACK_ALLOCATE | TT_DESCRIPTOR_INNER_CACHE_POLICY_WRITE_BACK_ALLOCATE)
+
+#define TT_DESCRIPTOR_SECTION_DOMAIN_MASK (0x0FUL << 5)
+#define TT_DESCRIPTOR_SECTION_DOMAIN(a) (((a) & 0x0FUL) << 5)
+
+#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK (0xFFF00000)
+#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) (a & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK)
+
+#define TT_DESCRIPTOR_SECTION_WRITE_BACK (TT_DESCRIPTOR_TYPE_SECTION | \
+ TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+ TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
+ TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_AP_RW_RW | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC)
+#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH (TT_DESCRIPTOR_TYPE_SECTION | \
+ TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+ TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
+ TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_AP_RW_RW | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC)
+#define TT_DESCRIPTOR_SECTION_UNCACHED (TT_DESCRIPTOR_TYPE_SECTION | \
+ TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+ TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
+ TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_AP_RW_RW | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE)
+
+#endif // __ARM1176JZ_S_H__
diff --git a/ArmPkg/Include/Chipset/ARM926EJ-S.h b/ArmPkg/Include/Chipset/ARM926EJ-S.h new file mode 100644 index 0000000000..799d60c392 --- /dev/null +++ b/ArmPkg/Include/Chipset/ARM926EJ-S.h @@ -0,0 +1,71 @@ +/** @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 __ARM926EJ_S_H__
+#define __ARM926EJ_S_H__
+
+// Domain Access Control Register
+#define DOMAIN_ACCESS_CONTROL_MASK(a) (3UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_NONE(a) (0UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_CLIENT(a) (1UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_RESERVED(a) (2UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_MANAGER(a) (3UL << (2 * (a)))
+
+#define TRANSLATION_TABLE_SIZE (16 * 1024)
+#define TRANSLATION_TABLE_ALIGNMENT (16 * 1024)
+#define TRANSLATION_TABLE_ALIGNMENT_MASK (TRANSLATION_TABLE_ALIGNMENT - 1)
+
+#define TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(table, address) ((UINT32 *)(table) + (((UINTN)(address)) >> 20))
+
+// Translation table descriptor types
+#define TT_DESCRIPTOR_TYPE_MASK (3UL << 0)
+#define TT_DESCRIPTOR_TYPE_FAULT (0UL << 0)
+#define TT_DESCRIPTOR_TYPE_COARSE ((1UL << 0) | (1UL << 4))
+#define TT_DESCRIPTOR_TYPE_SECTION ((2UL << 0) | (1UL << 4))
+#define TT_DESCRIPTOR_TYPE_FINE ((3UL << 0) | (1UL << 4))
+
+// Section descriptor definitions
+#define TT_DESCRIPTOR_SECTION_SIZE (0x00100000)
+
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK (3UL << 2)
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_UNCACHED_UNBUFFERED (0UL << 2)
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_UNCACHED_BUFFERED (1UL << 2)
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH (2UL << 2)
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK (3UL << 2)
+
+#define TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_MASK (3UL << 10)
+#define TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_NONE (1UL << 10)
+#define TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_ONLY (2UL << 10)
+#define TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_WRITE (3UL << 10)
+
+#define TT_DESCRIPTOR_SECTION_DOMAIN_MASK (0x0FUL << 5)
+#define TT_DESCRIPTOR_SECTION_DOMAIN(a) (((a) & 0xF) << 5)
+
+#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK (0xFFF00000)
+#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) (a & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK)
+
+#define TT_DESCRIPTOR_SECTION_WRITE_BACK (TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_WRITE | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK | \
+ TT_DESCRIPTOR_TYPE_SECTION)
+#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH (TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_WRITE | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH | \
+ TT_DESCRIPTOR_TYPE_SECTION)
+#define TT_DESCRIPTOR_SECTION_UNCACHED_UNBUFFERED (TT_DESCRIPTOR_SECTION_ACCESS_PERMISSION_READ_WRITE | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_UNCACHED_UNBUFFERED | \
+ TT_DESCRIPTOR_TYPE_SECTION)
+
+#endif // __ARM926EJ_S_H__
diff --git a/ArmPkg/Include/Chipset/Cortex-A8.h b/ArmPkg/Include/Chipset/Cortex-A8.h new file mode 100644 index 0000000000..75ce397a79 --- /dev/null +++ b/ArmPkg/Include/Chipset/Cortex-A8.h @@ -0,0 +1,104 @@ +/** @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 __CORTEX_A8_H__
+#define __CORTEX_A8_H__
+
+// Domain Access Control Register
+#define DOMAIN_ACCESS_CONTROL_MASK(a) (3UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_NONE(a) (0UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_CLIENT(a) (1UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_RESERVED(a) (2UL << (2 * (a)))
+#define DOMAIN_ACCESS_CONTROL_MANAGER(a) (3UL << (2 * (a)))
+
+#define TRANSLATION_TABLE_SIZE (16 * 1024)
+#define TRANSLATION_TABLE_ALIGNMENT (16 * 1024)
+#define TRANSLATION_TABLE_ALIGNMENT_MASK (TRANSLATION_TABLE_ALIGNMENT - 1)
+
+#define TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(table, address) ((UINT32 *)(table) + (((UINTN)(address)) >> 20))
+
+// Translation table descriptor types
+#define TT_DESCRIPTOR_TYPE_MASK ((1UL << 18) | (3UL << 0))
+#define TT_DESCRIPTOR_TYPE_PAGE_TABLE ((0UL << 18) | (1UL << 0))
+#define TT_DESCRIPTOR_TYPE_SECTION ((0UL << 18) | (2UL << 0))
+#define TT_DESCRIPTOR_TYPE_SUPERSECTION ((1UL << 18) | (2UL << 0))
+
+// Section descriptor definitions
+#define TT_DESCRIPTOR_SECTION_SIZE (0x00100000)
+
+#define TT_DESCRIPTOR_SECTION_NS_MASK (1UL << 19)
+#define TT_DESCRIPTOR_SECTION_NS_SECURE (0UL << 19)
+#define TT_DESCRIPTOR_SECTION_NS_NON_SECURE (1UL << 19)
+
+#define TT_DESCRIPTOR_SECTION_NG_MASK (1UL << 17)
+#define TT_DESCRIPTOR_SECTION_NG_GLOBAL (0UL << 17)
+#define TT_DESCRIPTOR_SECTION_NG_LOCAL (1UL << 17)
+
+#define TT_DESCRIPTOR_SECTION_S_MASK (1UL << 16)
+#define TT_DESCRIPTOR_SECTION_S_NOT_SHARED (0UL << 16)
+#define TT_DESCRIPTOR_SECTION_S_SHARED (1UL << 16)
+
+#define TT_DESCRIPTOR_SECTION_AP_MASK ((1UL << 15) | (3UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_NO_NO ((0UL << 15) | (0UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RW_NO ((0UL << 15) | (1UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RW_RO ((0UL << 15) | (2UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RW_RW ((0UL << 15) | (3UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RO_NO ((1UL << 15) | (1UL << 10))
+#define TT_DESCRIPTOR_SECTION_AP_RO_RO ((1UL << 15) | (3UL << 10))
+
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK ((3UL << 12) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED ((0UL << 12) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE ((0UL << 12) | (0UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC ((0UL << 12) | (1UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC ((0UL << 12) | (1UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE ((1UL << 12) | (0UL << 3) | (0UL << 2))
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC ((1UL << 12) | (1UL << 3) | (1UL << 2))
+#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE ((2UL << 12) | (0UL << 3) | (0UL << 2))
+
+#define TT_DESCRIPTOR_SECTION_DOMAIN_MASK (0x0FUL << 5)
+#define TT_DESCRIPTOR_SECTION_DOMAIN(a) (((a) & 0x0FUL) << 5)
+
+#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK (0xFFF00000)
+#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) (a & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK)
+
+#define TT_DESCRIPTOR_SECTION_WRITE_BACK (TT_DESCRIPTOR_TYPE_SECTION | \
+ TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+ TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
+ TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_AP_RW_RW | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC)
+#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH (TT_DESCRIPTOR_TYPE_SECTION | \
+ TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+ TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
+ TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_AP_RW_RW | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC)
+#define TT_DESCRIPTOR_SECTION_DEVICE (TT_DESCRIPTOR_TYPE_SECTION | \
+ TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+ TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
+ TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_AP_RW_RW | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE)
+#define TT_DESCRIPTOR_SECTION_UNCACHED (TT_DESCRIPTOR_TYPE_SECTION | \
+ TT_DESCRIPTOR_SECTION_NS_NON_SECURE | \
+ TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
+ TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
+ TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
+ TT_DESCRIPTOR_SECTION_AP_RW_RW | \
+ TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE)
+
+#endif // __CORTEX_A8_H__
diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h new file mode 100644 index 0000000000..d68b334e2a --- /dev/null +++ b/ArmPkg/Include/Library/ArmLib.h @@ -0,0 +1,294 @@ +/** @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 __ARM_LIB__ +#define __ARM_LIB__ + +typedef enum { + ARM_CACHE_TYPE_WRITE_BACK, + ARM_CACHE_TYPE_UNKNOWN +} ARM_CACHE_TYPE; + +typedef enum { + ARM_CACHE_ARCHITECTURE_UNIFIED, + ARM_CACHE_ARCHITECTURE_SEPARATE, + ARM_CACHE_ARCHITECTURE_UNKNOWN +} ARM_CACHE_ARCHITECTURE; + +typedef struct { + ARM_CACHE_TYPE Type; + ARM_CACHE_ARCHITECTURE Architecture; + BOOLEAN DataCachePresent; + UINTN DataCacheSize; + UINTN DataCacheAssociativity; + UINTN DataCacheLineLength; + BOOLEAN InstructionCachePresent; + UINTN InstructionCacheSize; + UINTN InstructionCacheAssociativity; + UINTN InstructionCacheLineLength; +} ARM_CACHE_INFO; + +typedef enum { + ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH, + ARM_MEMORY_REGION_ATTRIBUTE_DEVICE +} ARM_MEMORY_REGION_ATTRIBUTES; + +typedef struct { + UINT32 PhysicalBase; + UINT32 VirtualBase; + UINT32 Length; + ARM_MEMORY_REGION_ATTRIBUTES Attributes; +} ARM_MEMORY_REGION_DESCRIPTOR; + +typedef VOID (*CACHE_OPERATION)(VOID); +typedef VOID (*LINE_OPERATION)(UINTN); + +typedef enum { + ARM_PROCESSOR_MODE_USER = 0x10, + ARM_PROCESSOR_MODE_FIQ = 0x11, + ARM_PROCESSOR_MODE_IRQ = 0x12, + ARM_PROCESSOR_MODE_SUPERVISOR = 0x13, + ARM_PROCESSOR_MODE_ABORT = 0x17, + ARM_PROCESSOR_MODE_UNDEFINED = 0x1B, + ARM_PROCESSOR_MODE_SYSTEM = 0x1F, + ARM_PROCESSOR_MODE_MASK = 0x1F +} ARM_PROCESSOR_MODE; + +ARM_CACHE_TYPE +EFIAPI +ArmCacheType ( + VOID + ); + +ARM_CACHE_ARCHITECTURE +EFIAPI +ArmCacheArchitecture ( + VOID + ); + +VOID +EFIAPI +ArmCacheInformation ( + OUT ARM_CACHE_INFO *CacheInfo + ); + +BOOLEAN +EFIAPI +ArmDataCachePresent ( + VOID + ); + +UINTN +EFIAPI +ArmDataCacheSize ( + VOID + ); + +UINTN +EFIAPI +ArmDataCacheAssociativity ( + VOID + ); + +UINTN +EFIAPI +ArmDataCacheLineLength ( + VOID + ); + +BOOLEAN +EFIAPI +ArmInstructionCachePresent ( + VOID + ); + +UINTN +EFIAPI +ArmInstructionCacheSize ( + VOID + ); + +UINTN +EFIAPI +ArmInstructionCacheAssociativity ( + VOID + ); + +UINTN +EFIAPI +ArmInstructionCacheLineLength ( + VOID + ); + +UINT32 +EFIAPI +Cp15IdCode ( + VOID + ); + +UINT32 +EFIAPI +Cp15CacheInfo ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateDataCache ( + VOID + ); + +VOID +EFIAPI +ArmCleanInvalidateDataCache ( + VOID + ); + +VOID +EFIAPI +ArmCleanDataCache ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateInstructionCache ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateDataCacheEntryByMVA ( + IN UINTN Address + ); + +VOID +EFIAPI +ArmCleanDataCacheEntryByMVA ( + IN UINTN Address + ); + +VOID +EFIAPI +ArmCleanInvalidateDataCacheEntryByMVA ( + IN UINTN Address + ); + +VOID +EFIAPI +ArmEnableDataCache ( + VOID + ); + +VOID +EFIAPI +ArmDisableDataCache ( + VOID + ); + +VOID +EFIAPI +ArmEnableInstructionCache ( + VOID + ); + +VOID +EFIAPI +ArmDisableInstructionCache ( + VOID + ); + +VOID +EFIAPI +ArmEnableMmu ( + VOID + ); + +VOID +EFIAPI +ArmDisableMmu ( + VOID + ); + +VOID +EFIAPI +ArmEnableInterrupts ( + VOID + ); + +UINTN +EFIAPI +ArmDisableInterrupts ( + VOID + ); + +BOOLEAN +EFIAPI +ArmGetInterruptState ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateTlb ( + VOID + ); + +VOID +EFIAPI +ArmSetDomainAccessControl ( + IN UINT32 Domain + ); + +VOID +EFIAPI +ArmSetTranslationTableBaseAddress ( + IN VOID *TranslationTableBase + ); + +VOID +EFIAPI +ArmConfigureMmu ( + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable, + OUT VOID **TranslationTableBase OPTIONAL, + OUT UINTN *TranslationTableSize OPTIONAL + ); + +VOID +EFIAPI +ArmSwitchProcessorMode ( + IN ARM_PROCESSOR_MODE Mode + ); + +ARM_PROCESSOR_MODE +EFIAPI +ArmProcessorMode ( + VOID + ); + +VOID +EFIAPI +ArmEnableBranchPrediction ( + VOID + ); + +VOID +EFIAPI +ArmDisableBranchPrediction ( + VOID + ); + +#endif // __ARM_LIB__ diff --git a/ArmPkg/Include/Library/SemihostLib.h b/ArmPkg/Include/Library/SemihostLib.h new file mode 100644 index 0000000000..2c8b6ac7d8 --- /dev/null +++ b/ArmPkg/Include/Library/SemihostLib.h @@ -0,0 +1,100 @@ +/** @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 __SEMIHOSTING_H__ +#define __SEMIHOSTING_H__ + +/* + * + * Please refer to ARM RVDS 3.0 Compiler and Libraries Guide for more information + * about the semihosting interface. + * + */ + +#define SEMIHOST_FILE_MODE_READ (0 << 2) +#define SEMIHOST_FILE_MODE_WRITE (1 << 2) +#define SEMIHOST_FILE_MODE_APPEND (2 << 2) +#define SEMIHOST_FILE_MODE_CREATE (1 << 1) +#define SEMIHOST_FILE_MODE_BINARY (1 << 0) +#define SEMIHOST_FILE_MODE_ASCII (0 << 0) + +BOOLEAN +SemihostConnectionSupported ( + VOID + ); + +EFI_STATUS +SemihostFileOpen ( + IN CHAR8 *FileName, + IN UINT32 Mode, + OUT UINT32 *FileHandle + ); + +EFI_STATUS +SemihostFileSeek ( + IN UINT32 FileHandle, + IN UINT32 Offset + ); + +EFI_STATUS +SemihostFileRead ( + IN UINT32 FileHandle, + IN OUT UINT32 *Length, + OUT VOID *Buffer + ); + +EFI_STATUS +SemihostFileWrite ( + IN UINT32 FileHandle, + IN OUT UINT32 *Length, + IN VOID *Buffer + ); + +EFI_STATUS +SemihostFileClose ( + IN UINT32 FileHandle + ); + +EFI_STATUS +SemihostFileLength ( + IN UINT32 FileHandle, + OUT UINT32 *Length + ); + +EFI_STATUS +SemihostFileRemove ( + IN CHAR8 *FileName + ); + +CHAR8 +SemihostReadCharacter ( + VOID + ); + +VOID +SemihostWriteCharacter ( + IN CHAR8 Character + ); + +VOID +SemihostWriteString ( + IN CHAR8 *String + ); + +UINT32 +SemihostSystem ( + IN CHAR8 *CommandLine + ); + +#endif // __SEMIHOSTING_H__ diff --git a/ArmPkg/Include/Library/UncachedMemoryAllocationLib.h b/ArmPkg/Include/Library/UncachedMemoryAllocationLib.h new file mode 100644 index 0000000000..8a65fcc586 --- /dev/null +++ b/ArmPkg/Include/Library/UncachedMemoryAllocationLib.h @@ -0,0 +1,665 @@ +/** @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 __UNCACHED_MEMORY_ALLOCATION_LIB_H__ +#define __UNCACHED_MEMORY_ALLOCATION_LIB_H__ + +/** + Converts a cached or uncached address to a physical address suitable for use in SoC registers. + + @param VirtualAddress The pointer to convert. + + @return The physical address of the supplied virtual pointer. + +**/ +EFI_PHYSICAL_ADDRESS +ConvertToPhysicalAddress ( + IN VOID *VirtualAddress + ); + +/** + Converts a cached or uncached address to a cached address. + + @param Address The pointer to convert. + + @return The address of the cached memory location corresponding to the input address. + +**/ +VOID * +ConvertToCachedAddress ( + IN VOID *Address + ); + +/** + Converts a cached or uncached address to an uncached address. + + @param Address The pointer to convert. + + @return The address of the uncached memory location corresponding to the input address. + +**/ +VOID * +ConvertToUncachedAddress ( + IN VOID *Address + ); + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of type EfiBootServicesData 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 +UncachedAllocatePages ( + IN UINTN Pages + ); + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData. + + Allocates the number of 4KB pages of type EfiRuntimeServicesData 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 +UncachedAllocateRuntimePages ( + IN UINTN Pages + ); + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType. + + Allocates the number of 4KB pages of type EfiReservedMemoryType 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 +UncachedAllocateReservedPages ( + IN UINTN Pages + ); + +/** + Frees one or more 4KB pages that were previously allocated with one of the page allocation + functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the page allocation services of the Memory + Allocation Library. + If Buffer was not allocated with a page allocation function in the Memory Allocation Library, + then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +UncachedFreePages ( + IN VOID *Buffer, + IN UINTN Pages + ); + +/** + 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 +UncachedAllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +/** + Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData 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 +UncachedAllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType 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 +UncachedAllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ); + +/** + Frees one or more 4KB pages that were previously allocated with one of the aligned page + allocation functions in the Memory Allocation Library. + + Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer. Buffer + must have been allocated on a previous call to the aligned page allocation services of the Memory + Allocation Library. + If Buffer was not allocated with an aligned page allocation function in the Memory Allocation + Library, then ASSERT(). + If Pages is zero, then ASSERT(). + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +UncachedFreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ); + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocatePool ( + IN UINTN AllocationSize + ); + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData 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 +UncachedAllocateRuntimePool ( + IN UINTN AllocationSize + ); + +/** + Allocates a buffer of type EfieservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType 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 +UncachedAllocateReservedPool ( + IN UINTN AllocationSize + ); + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the + buffer with zeros, 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 and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateZeroPool ( + IN UINTN AllocationSize + ); + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the + buffer with zeros, 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 and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ); + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the + buffer with zeros, 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 and zero. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedZeroPool ( + IN UINTN AllocationSize + ); + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, 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. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies + AllocationSize bytes from Buffer to the newly allocated buffer, 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. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies + AllocationSize bytes from Buffer to the newly allocated buffer, 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. + If Buffer is NULL, then ASSERT(). + If AllocationSize is greater than (MAX_ADDRESS ? Buffer + 1), then ASSERT(). + + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +UncachedAllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ); + +/** + Frees a buffer that was previously allocated with one of the pool allocation functions in the + Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + pool allocation services of the Memory Allocation Library. + If Buffer was not allocated with a pool allocation function in the Memory Allocation Library, + then ASSERT(). + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +UncachedFreePool ( + IN VOID *Buffer + ); + +/** + Allocates a buffer of type EfiBootServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size 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 AllocationSize The number of bytes 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 +UncachedAllocateAlignedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates a buffer of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size 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 AllocationSize The number of bytes 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 +UncachedAllocateAlignedRuntimePool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates a buffer of type EfieservedMemoryType at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size 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 AllocationSize The number of bytes 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 +UncachedAllocateAlignedReservedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData with an + alignment specified by Alignment, clears the buffer with zeros, 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 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 AllocationSize The number of bytes 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 +UncachedAllocateAlignedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData with an + alignment specified by Alignment, clears the buffer with zeros, 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 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 AllocationSize The number of bytes 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 +UncachedAllocateAlignedRuntimeZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Allocates and zeros a buffer of type EfieservedMemoryType at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfieservedMemoryType with an + alignment specified by Alignment, clears the buffer with zeros, 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 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 AllocationSize The number of bytes 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 +UncachedAllocateAlignedReservedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ); + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData type with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size 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 AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @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 +UncachedAllocateAlignedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ); + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData type with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size 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 AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @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 +UncachedAllocateAlignedRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ); + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment. + + Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType type with an + alignment specified by Alignment. The allocated buffer is returned. If AllocationSize is 0, + then a valid buffer of 0 size 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 AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @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 +UncachedAllocateAlignedReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ); + +/** + Frees a buffer that was previously allocated with one of the aligned pool allocation functions + in the Memory Allocation Library. + + Frees the buffer specified by Buffer. Buffer must have been allocated on a previous call to the + aligned pool allocation services of the Memory Allocation Library. + If Buffer was not allocated with an aligned pool allocation function in the Memory Allocation + Library, then ASSERT(). + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +UncachedFreeAlignedPool ( + IN VOID *Buffer + ); + +VOID +EFIAPI +UncachedSafeFreePool ( + IN VOID *Buffer + ); + +#endif // __UNCACHED_MEMORY_ALLOCATION_LIB_H__ diff --git a/ArmPkg/Include/Protocol/TimerDebugSupport.h b/ArmPkg/Include/Protocol/TimerDebugSupport.h new file mode 100644 index 0000000000..8ed9254176 --- /dev/null +++ b/ArmPkg/Include/Protocol/TimerDebugSupport.h @@ -0,0 +1,59 @@ +/** @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 __TIMERDEBUGSUPPORTPROTOCOL_H__
+#define __TIMERDEBUGSUPPORTPROTOCOL_H__
+
+//
+// Protocol GUID
+//
+#define TIMER_DEBUG_PROTOCOL_GUID { 0x68300561, 0x0197, 0x465d, { 0xb5, 0xa1, 0x28, 0xeb, 0xa1, 0x98, 0xdd, 0x0b } }
+
+
+
+//
+// Protocol interface structure
+//
+typedef struct _TIMER_DEBUG_SUPPORT_PROTOCOL TIMER_DEBUG_SUPPORT_PROTOCOL;
+
+
+typedef
+EFI_STATUS
+(EFIAPI *TIMER_DEBUG_SUPPORT_REGISTER_PERIODIC_CALLBACK) (
+ IN TIMER_DEBUG_SUPPORT_PROTOCOL *This,
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback
+ )
+/*++
+
+Routine Description:
+ Register a periodic callback for debug support.
+
+Arguments:
+ This - pointer to protocol
+ PeriodicCallback - callback to be registered
+
+Returns:
+ EFI_SUCCESS - callback registered
+
+--*/
+;
+
+struct _TIMER_DEBUG_SUPPORT_PROTOCOL {
+ TIMER_DEBUG_SUPPORT_REGISTER_PERIODIC_CALLBACK RegisterPeriodicCallback;
+};
+
+extern EFI_GUID gTimerDebugSupportProtocolGuid;
+
+#endif // __TIMERDEBUGSUPPORTPROTOCOL_H__
+
diff --git a/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c new file mode 100644 index 0000000000..7da6b42a92 --- /dev/null +++ b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c @@ -0,0 +1,129 @@ +/** @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 <Base.h> +#include <Library/ArmLib.h> +#include <Library/PcdLib.h> + +VOID +CacheRangeOperation ( + IN VOID *Start, + IN UINTN Length, + IN CACHE_OPERATION CacheOperation, + IN LINE_OPERATION LineOperation + ) +{ + UINTN ArmCacheLineLength = ArmDataCacheLineLength(); + UINTN ArmCacheLineAlignmentMask = ArmCacheLineLength - 1; + UINTN ArmCacheOperationThreshold = PcdGet32(PcdArmCacheOperationThreshold); + + if ((CacheOperation != NULL) && (Length >= ArmCacheOperationThreshold)) + { + CacheOperation(); + } + else + { + // Align address (rounding down) + UINTN AlignedAddress = (UINTN)Start - ((UINTN)Start & ArmCacheLineAlignmentMask); + UINTN EndAddress = (UINTN)Start + Length; + + // Perform the line operation on an address in each cache line + while (AlignedAddress < EndAddress) + { + LineOperation(AlignedAddress); + AlignedAddress += ArmCacheLineLength; + } + } +} + +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ + ArmCleanDataCache(); + ArmInvalidateInstructionCache(); +} + +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ + ArmInvalidateDataCache(); +} + +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + CacheRangeOperation(Address, Length, ArmCleanDataCache, ArmCleanDataCacheEntryByMVA); + ArmInvalidateInstructionCache(); + return Address; +} + +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + ArmCleanInvalidateDataCache(); +} + +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + CacheRangeOperation(Address, Length, ArmCleanInvalidateDataCache, ArmCleanInvalidateDataCacheEntryByMVA); + return Address; +} + +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + ArmCleanDataCache(); +} + +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + CacheRangeOperation(Address, Length, ArmCleanDataCache, ArmCleanDataCacheEntryByMVA); + return Address; +} + +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + CacheRangeOperation(Address, Length, NULL, ArmInvalidateDataCacheEntryByMVA); + return Address; +} diff --git a/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf new file mode 100644 index 0000000000..93b88f4ef0 --- /dev/null +++ b/ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf @@ -0,0 +1,23 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmCacheMaintenanceLib + FILE_GUID = 1A20BE1F-33AD-450C-B49A-7123FCA8B7F9 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CacheMaintenanceLib + +[Sources.common] + ArmCacheMaintenanceLib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmLib + BaseLib + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmCacheOperationThreshold + diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf b/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf new file mode 100644 index 0000000000..8042e4dd31 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLib.inf @@ -0,0 +1,32 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Arm11ArmLib
+ FILE_GUID = 00586300-0E06-4790-AC44-86C56ACBB942
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ../Common/ArmLibSupport.S | GCC
+ ../Common/ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ Arm11Support.S | GCC
+ Arm11Support.asm | RVCT
+
+ Arm11Lib.c
+ ../Arm9/Arm9CacheInformation.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf b/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf new file mode 100644 index 0000000000..040179e445 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11ArmLibPrePi.inf @@ -0,0 +1,32 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Arm11ArmLib
+ FILE_GUID = 8dfb4ea2-3901-44f9-ae54-ca3d50362d2f
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ../Common/ArmLibSupport.S | GCC
+ ../Common/ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ Arm11Support.S | GCC
+ Arm11Support.asm | RVCT
+
+ Arm11Lib.c
+ ../Arm9/Arm9CacheInformation.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ PrePiLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c b/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c new file mode 100644 index 0000000000..3736904954 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11Lib.c @@ -0,0 +1,118 @@ +/** @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 <Chipset/ARM1176JZ-S.h> +#include <Library/ArmLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> + +VOID +FillTranslationTable ( + IN UINT32 *TranslationTable, + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion + ) +{ + UINT32 *Entry; + UINTN Sections; + UINTN Index; + UINT32 Attributes; + UINT32 PhysicalBase = MemoryRegion->PhysicalBase; + + switch (MemoryRegion->Attributes) { + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED: + default: + Attributes = TT_DESCRIPTOR_SECTION_UNCACHED; + break; + } + + Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase); + Sections = ((( MemoryRegion->Length - 1 ) / TT_DESCRIPTOR_SECTION_SIZE ) + 1 ); + + for (Index = 0; Index < Sections; Index++) + { + *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes; + PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE; + } +} + +VOID +EFIAPI +ArmConfigureMmu ( + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable, + OUT VOID **TranslationTableBase OPTIONAL, + OUT UINTN *TranslationTableSize OPTIONAL + ) +{ + VOID *TranslationTable; + + // Allocate pages for translation table. + TranslationTable = AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SIZE + TRANSLATION_TABLE_ALIGNMENT)); + TranslationTable = (VOID *)(((UINTN)TranslationTable + TRANSLATION_TABLE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_ALIGNMENT_MASK); + + if (TranslationTableBase != NULL) { + *TranslationTableBase = TranslationTable; + } + + if (TranslationTableBase != NULL) { + *TranslationTableSize = TRANSLATION_TABLE_SIZE; + } + + ZeroMem(TranslationTable, TRANSLATION_TABLE_SIZE); + + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + ArmInvalidateTlb(); + + ArmDisableDataCache(); + ArmDisableInstructionCache(); + ArmDisableMmu(); + + // Make sure nothing sneaked into the cache + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + + while (MemoryTable->Length != 0) { + FillTranslationTable(TranslationTable, MemoryTable); + MemoryTable++; + } + + ArmSetTranslationTableBaseAddress(TranslationTable); + + ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) | + DOMAIN_ACCESS_CONTROL_NONE(14) | + DOMAIN_ACCESS_CONTROL_NONE(13) | + DOMAIN_ACCESS_CONTROL_NONE(12) | + DOMAIN_ACCESS_CONTROL_NONE(11) | + DOMAIN_ACCESS_CONTROL_NONE(10) | + DOMAIN_ACCESS_CONTROL_NONE( 9) | + DOMAIN_ACCESS_CONTROL_NONE( 8) | + DOMAIN_ACCESS_CONTROL_NONE( 7) | + DOMAIN_ACCESS_CONTROL_NONE( 6) | + DOMAIN_ACCESS_CONTROL_NONE( 5) | + DOMAIN_ACCESS_CONTROL_NONE( 4) | + DOMAIN_ACCESS_CONTROL_NONE( 3) | + DOMAIN_ACCESS_CONTROL_NONE( 2) | + DOMAIN_ACCESS_CONTROL_NONE( 1) | + DOMAIN_ACCESS_CONTROL_MANAGER(0)); + + ArmEnableInstructionCache(); + ArmEnableDataCache(); + ArmEnableMmu(); +} diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S new file mode 100644 index 0000000000..eec8f20b4e --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.S @@ -0,0 +1,129 @@ +#------------------------------------------------------------------------------ +# +# 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 ASM_PFX(ArmCleanInvalidateDataCache) +.globl ASM_PFX(ArmCleanDataCache) +.globl ASM_PFX(ArmInvalidateDataCache) +.globl ASM_PFX(ArmInvalidateInstructionCache) +.globl ASM_PFX(ArmInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmEnableMmu) +.globl ASM_PFX(ArmDisableMmu) +.globl ASM_PFX(ArmEnableDataCache) +.globl ASM_PFX(ArmDisableDataCache) +.globl ASM_PFX(ArmEnableInstructionCache) +.globl ASM_PFX(ArmDisableInstructionCache) +.globl ASM_PFX(ArmEnableBranchPrediction) +.globl ASM_PFX(ArmDisableBranchPrediction) + +.set DC_ON, (0x1<<2) +.set IC_ON, (0x1<<12) +.set XP_ON, (0x1<<23) + +ASM_PFX(ArmInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c6, 1 @invalidate single data cache line + bx lr + + +ASM_PFX(ArmCleanDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c10, 1 @clean single data cache line + bx lr + + +ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c14, 1 @clean and invalidate single data cache line + bx lr + + +ASM_PFX(ArmCleanDataCache): + mcr p15, 0, r0, c7, c10, 0 @ clean entire data cache + bx lr + + +ASM_PFX(ArmCleanInvalidateDataCache): + mcr p15, 0, r0, c7, c14, 0 @ clean and invalidate entire data cache + bx lr + + +ASM_PFX(ArmInvalidateDataCache): + mcr p15, 0, r0, c7, c6, 0 @ invalidate entire data cache + bx lr + + +ASM_PFX(ArmInvalidateInstructionCache): + mcr p15, 0, r0, c7, c5, 0 @invalidate entire instruction cache + mov R0,#0 + mcr p15,0,R0,c7,c5,4 @Flush Prefetch buffer + bx lr + +ASM_PFX(ArmEnableMmu): + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ASM_PFX(ArmDisableMmu): + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Data synchronization barrier + mov R0,#0 + mcr p15,0,R0,c7,c5,4 @Flush Prefetch buffer + bx LR + +ASM_PFX(ArmEnableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmEnableInstructionCache): + ldr R1,=IC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set I bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableInstructionCache): + ldr R1,=IC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear I bit. + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmEnableBranchPrediction): + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ASM_PFX(ArmDisableBranchPrediction): + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/ArmPkg/Library/ArmLib/Arm11/Arm11Support.asm b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.asm new file mode 100644 index 0000000000..e0be8f0c07 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm11/Arm11Support.asm @@ -0,0 +1,133 @@ +//------------------------------------------------------------------------------ +// +// 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 ArmCleanInvalidateDataCache + EXPORT ArmCleanDataCache + EXPORT ArmInvalidateDataCache + EXPORT ArmInvalidateInstructionCache + EXPORT ArmInvalidateDataCacheEntryByMVA + EXPORT ArmCleanDataCacheEntryByMVA + EXPORT ArmCleanInvalidateDataCacheEntryByMVA + EXPORT ArmEnableMmu + EXPORT ArmDisableMmu + EXPORT ArmEnableDataCache + EXPORT ArmDisableDataCache + EXPORT ArmEnableInstructionCache + EXPORT ArmDisableInstructionCache + EXPORT ArmEnableBranchPrediction + EXPORT ArmDisableBranchPrediction + + +DC_ON EQU ( 0x1:SHL:2 ) +IC_ON EQU ( 0x1:SHL:12 ) +XP_ON EQU ( 0x1:SHL:23 ) + + + AREA ArmCacheLib, CODE, READONLY + PRESERVE8 + + +ArmInvalidateDataCacheEntryByMVA + mcr p15, 0, r0, c7, c6, 1 ; invalidate single data cache line + bx lr + + +ArmCleanDataCacheEntryByMVA + mcr p15, 0, r0, c7, c10, 1 ; clean single data cache line + bx lr + + +ArmCleanInvalidateDataCacheEntryByMVA + mcr p15, 0, r0, c7, c14, 1 ; clean and invalidate single data cache line + bx lr + + +ArmCleanDataCache + mcr p15, 0, r0, c7, c10, 0 ; clean entire data cache + bx lr + + +ArmCleanInvalidateDataCache + mcr p15, 0, r0, c7, c14, 0 ; clean and invalidate entire data cache + bx lr + + +ArmInvalidateDataCache + mcr p15, 0, r0, c7, c6, 0 ; invalidate entire data cache + bx lr + + +ArmInvalidateInstructionCache + mcr p15, 0, r0, c7, c5, 0 ;invalidate entire instruction cache + mov R0,#0 + mcr p15,0,R0,c7,c5,4 ;Flush Prefetch buffer + bx lr + +ArmEnableMmu + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ArmDisableMmu + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + mov R0,#0 + mcr p15,0,R0,c7,c10,4 ;Data synchronization barrier + mov R0,#0 + mcr p15,0,R0,c7,c5,4 ;Flush Prefetch buffer + bx LR + +ArmEnableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmEnableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set I bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear I bit. + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmEnableBranchPrediction + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ArmDisableBranchPrediction + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + + END diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf b/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf new file mode 100644 index 0000000000..9a940394e2 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLib.inf @@ -0,0 +1,32 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Arm9ArmLib
+ FILE_GUID = 375D70D3-91E0-4374-A540-68BD959EB184
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ../Common/ArmLibSupport.S | GCC
+ ../Common/ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ Arm9Support.S | GCC
+ Arm9Support.asm | RVCT
+
+ Arm9Lib.c
+ Arm9CacheInformation.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf b/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf new file mode 100755 index 0000000000..909ce27616 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9ArmLibPrePi.inf @@ -0,0 +1,32 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Arm9ArmLibPrePi
+ FILE_GUID = e9b6011f-ee15-4e59-ab8f-a819a081fa54
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ../Common/ArmLibSupport.S | GCC
+ ../Common/ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ Arm9Support.S | GCC
+ Arm9Support.asm | RVCT
+
+ Arm9Lib.c
+ Arm9CacheInformation.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ PrePiLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9CacheInformation.c b/ArmPkg/Library/ArmLib/Arm9/Arm9CacheInformation.c new file mode 100644 index 0000000000..a8207b905f --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9CacheInformation.c @@ -0,0 +1,164 @@ +/** @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 <Library/ArmLib.h>
+#include "ArmLibPrivate.h"
+
+ARM_CACHE_TYPE
+EFIAPI
+ArmCacheType (
+ VOID
+ )
+{
+ switch (CACHE_TYPE(Cp15CacheInfo()))
+ {
+ case CACHE_TYPE_WRITE_BACK: return ARM_CACHE_TYPE_WRITE_BACK;
+ default: return ARM_CACHE_TYPE_UNKNOWN;
+ }
+}
+
+ARM_CACHE_ARCHITECTURE
+EFIAPI
+ArmCacheArchitecture (
+ VOID
+ )
+{
+ switch (CACHE_ARCHITECTURE(Cp15CacheInfo()))
+ {
+ case CACHE_ARCHITECTURE_UNIFIED: return ARM_CACHE_ARCHITECTURE_UNIFIED;
+ case CACHE_ARCHITECTURE_SEPARATE: return ARM_CACHE_ARCHITECTURE_SEPARATE;
+ default: return ARM_CACHE_ARCHITECTURE_UNKNOWN;
+ }
+}
+
+BOOLEAN
+EFIAPI
+ArmDataCachePresent (
+ VOID
+ )
+{
+ switch (DATA_CACHE_PRESENT(Cp15CacheInfo()))
+ {
+ case CACHE_PRESENT: return TRUE;
+ case CACHE_NOT_PRESENT: return FALSE;
+ default: return FALSE;
+ }
+}
+
+UINTN
+EFIAPI
+ArmDataCacheSize (
+ VOID
+ )
+{
+ switch (DATA_CACHE_SIZE(Cp15CacheInfo()))
+ {
+ case CACHE_SIZE_4_KB: return 4 * 1024;
+ case CACHE_SIZE_8_KB: return 8 * 1024;
+ case CACHE_SIZE_16_KB: return 16 * 1024;
+ case CACHE_SIZE_32_KB: return 32 * 1024;
+ case CACHE_SIZE_64_KB: return 64 * 1024;
+ case CACHE_SIZE_128_KB: return 128 * 1024;
+ default: return 0;
+ }
+}
+
+UINTN
+EFIAPI
+ArmDataCacheAssociativity (
+ VOID
+ )
+{
+ switch (DATA_CACHE_ASSOCIATIVITY(Cp15CacheInfo()))
+ {
+ case CACHE_ASSOCIATIVITY_4_WAY: return 4;
+ case CACHE_ASSOCIATIVITY_DIRECT: return 1;
+ default: return 0;
+ }
+}
+
+UINTN
+EFIAPI
+ArmDataCacheLineLength (
+ VOID
+ )
+{
+ switch (DATA_CACHE_LINE_LENGTH(Cp15CacheInfo()))
+ {
+ case CACHE_LINE_LENGTH_32_BYTES: return 32;
+ default: return 0;
+ }
+}
+
+BOOLEAN
+EFIAPI
+ArmInstructionCachePresent (
+ VOID
+ )
+{
+ switch (INSTRUCTION_CACHE_PRESENT(Cp15CacheInfo()))
+ {
+ case CACHE_PRESENT: return TRUE;
+ case CACHE_NOT_PRESENT: return FALSE;
+ default: return FALSE;
+ }
+}
+
+UINTN
+EFIAPI
+ArmInstructionCacheSize (
+ VOID
+ )
+{
+ switch (INSTRUCTION_CACHE_SIZE(Cp15CacheInfo()))
+ {
+ case CACHE_SIZE_4_KB: return 4 * 1024;
+ case CACHE_SIZE_8_KB: return 8 * 1024;
+ case CACHE_SIZE_16_KB: return 16 * 1024;
+ case CACHE_SIZE_32_KB: return 32 * 1024;
+ case CACHE_SIZE_64_KB: return 64 * 1024;
+ case CACHE_SIZE_128_KB: return 128 * 1024;
+ default: return 0;
+ }
+}
+
+UINTN
+EFIAPI
+ArmInstructionCacheAssociativity (
+ VOID
+ )
+{
+ switch (INSTRUCTION_CACHE_ASSOCIATIVITY(Cp15CacheInfo()))
+ {
+ case CACHE_ASSOCIATIVITY_8_WAY: return 8;
+ case CACHE_ASSOCIATIVITY_4_WAY: return 4;
+ case CACHE_ASSOCIATIVITY_DIRECT: return 1;
+ default: return 0;
+ }
+}
+
+UINTN
+EFIAPI
+ArmInstructionCacheLineLength (
+ VOID
+ )
+{
+ switch (INSTRUCTION_CACHE_LINE_LENGTH(Cp15CacheInfo()))
+ {
+ case CACHE_LINE_LENGTH_32_BYTES: return 32;
+ default: return 0;
+ }
+}
+
+
diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c b/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c new file mode 100644 index 0000000000..0ba2237d29 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9Lib.c @@ -0,0 +1,118 @@ +/** @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 <Chipset/ARM926EJ-S.h> +#include <Library/ArmLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> + +VOID +FillTranslationTable ( + IN UINT32 *TranslationTable, + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion + ) +{ + UINT32 *Entry; + UINTN Sections; + UINTN Index; + UINT32 Attributes; + UINT32 PhysicalBase = MemoryRegion->PhysicalBase; + + switch (MemoryRegion->Attributes) { + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED: + default: + Attributes = TT_DESCRIPTOR_SECTION_UNCACHED_UNBUFFERED; + break; + } + + Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase); + Sections = MemoryRegion->Length / TT_DESCRIPTOR_SECTION_SIZE; + + for (Index = 0; Index < Sections; Index++) + { + *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes; + PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE; + } +} + +VOID +EFIAPI +ArmConfigureMmu ( + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable, + OUT VOID **TranslationTableBase OPTIONAL, + OUT UINTN *TranslationTableSize OPTIONAL + ) +{ + VOID *TranslationTable; + + // Allocate pages for translation table. + TranslationTable = AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SIZE + TRANSLATION_TABLE_ALIGNMENT)); + TranslationTable = (VOID *)(((UINTN)TranslationTable + TRANSLATION_TABLE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_ALIGNMENT_MASK); + + if (TranslationTableBase != NULL) { + *TranslationTableBase = TranslationTable; + } + + if (TranslationTableBase != NULL) { + *TranslationTableSize = TRANSLATION_TABLE_SIZE; + } + + ZeroMem(TranslationTable, TRANSLATION_TABLE_SIZE); + + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + ArmInvalidateTlb(); + + ArmDisableDataCache(); + ArmDisableInstructionCache(); + ArmDisableMmu(); + + // Make sure nothing sneaked into the cache + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + + while (MemoryTable->Length != 0) { + FillTranslationTable(TranslationTable, MemoryTable); + MemoryTable++; + } + + ArmSetTranslationTableBaseAddress(TranslationTable); + + ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) | + DOMAIN_ACCESS_CONTROL_NONE(14) | + DOMAIN_ACCESS_CONTROL_NONE(13) | + DOMAIN_ACCESS_CONTROL_NONE(12) | + DOMAIN_ACCESS_CONTROL_NONE(11) | + DOMAIN_ACCESS_CONTROL_NONE(10) | + DOMAIN_ACCESS_CONTROL_NONE( 9) | + DOMAIN_ACCESS_CONTROL_NONE( 8) | + DOMAIN_ACCESS_CONTROL_NONE( 7) | + DOMAIN_ACCESS_CONTROL_NONE( 6) | + DOMAIN_ACCESS_CONTROL_NONE( 5) | + DOMAIN_ACCESS_CONTROL_NONE( 4) | + DOMAIN_ACCESS_CONTROL_NONE( 3) | + DOMAIN_ACCESS_CONTROL_NONE( 2) | + DOMAIN_ACCESS_CONTROL_NONE( 1) | + DOMAIN_ACCESS_CONTROL_MANAGER(0)); + + ArmEnableInstructionCache(); + ArmEnableDataCache(); + ArmEnableMmu(); +} diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S new file mode 100644 index 0000000000..5c9afe9347 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.S @@ -0,0 +1,128 @@ +#------------------------------------------------------------------------------ +# +# 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 ASM_PFX(ArmCleanInvalidateDataCache) +.globl ASM_PFX(ArmCleanDataCache) +.globl ASM_PFX(ArmInvalidateDataCache) +.globl ASM_PFX(ArmInvalidateInstructionCache) +.globl ASM_PFX(ArmInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmEnableMmu) +.globl ASM_PFX(ArmDisableMmu) +.globl ASM_PFX(ArmEnableDataCache) +.globl ASM_PFX(ArmDisableDataCache) +.globl ASM_PFX(ArmEnableInstructionCache) +.globl ASM_PFX(ArmDisableInstructionCache) +.globl ASM_PFX(ArmEnableBranchPrediction) +.globl ASM_PFX(ArmDisableBranchPrediction) + +.set DC_ON, (1<<2) +.set IC_ON, (1<<12) + +#------------------------------------------------------------------------------ + +ASM_PFX(ArmInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c6, 1 @ invalidate single data cache line + bx lr + +ASM_PFX(ArmCleanDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c10, 1 @ clean single data cache line + bx lr + +ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate single data cache line + bx lr + +ASM_PFX(ArmEnableInstructionCache): + ldr r1,=IC_ON + mrc p15,0,r0,c1,c0,0 @Read control register configuration data + orr r0,r0,r1 @Set I bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableInstructionCache): + ldr r1,=IC_ON + mrc p15,0,r0,c1,c0,0 @Read control register configuration data + bic r0,r0,r1 @Clear I bit. + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmInvalidateInstructionCache): + mov r0,#0 + mcr p15,0,r0,c7,c5,0 @Invalidate entire Instruction cache. + @Also flushes the branch target cache. + mov r0,#0 + mcr p15,0,r0,c7,c10,4 @Data write buffer + bx LR + +ASM_PFX(ArmEnableMmu): + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ASM_PFX(ArmDisableMmu): + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Drain write buffer + bx LR + +ASM_PFX(ArmEnableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmCleanDataCache): + mrc p15,0,r15,c7,c10,3 + bne ASM_PFX(ArmCleanDataCache) + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Drain write buffer + bx LR + +ASM_PFX(ArmInvalidateDataCache): + mov R0,#0 + mcr p15,0,R0,c7,c6,0 @Invalidate entire data cache + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Drain write buffer + bx LR + +ASM_PFX(ArmCleanInvalidateDataCache): + mrc p15,0,r15,c7,c14,3 + bne ASM_PFX(ArmCleanInvalidateDataCache) + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Drain write buffer + bx LR + +ASM_PFX(ArmEnableBranchPrediction): + bx LR @Branch prediction is not supported. + +ASM_PFX(ArmDisableBranchPrediction): + bx LR @Branch prediction is not supported. + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED + diff --git a/ArmPkg/Library/ArmLib/Arm9/Arm9Support.asm b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.asm new file mode 100644 index 0000000000..3204d6607f --- /dev/null +++ b/ArmPkg/Library/ArmLib/Arm9/Arm9Support.asm @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------ +// +// 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 ArmCleanInvalidateDataCache + EXPORT ArmCleanDataCache + EXPORT ArmInvalidateDataCache + EXPORT ArmInvalidateInstructionCache + EXPORT ArmInvalidateDataCacheEntryByMVA + EXPORT ArmCleanDataCacheEntryByMVA + EXPORT ArmCleanInvalidateDataCacheEntryByMVA + EXPORT ArmEnableMmu + EXPORT ArmDisableMmu + EXPORT ArmEnableDataCache + EXPORT ArmDisableDataCache + EXPORT ArmEnableInstructionCache + EXPORT ArmDisableInstructionCache + EXPORT ArmEnableBranchPrediction + EXPORT ArmDisableBranchPrediction + + +DC_ON EQU ( 0x1:SHL:2 ) +IC_ON EQU ( 0x1:SHL:12 ) + + AREA ArmCacheLib, CODE, READONLY + PRESERVE8 + + +ArmInvalidateDataCacheEntryByMVA + MCR p15, 0, r0, c7, c6, 1 ; invalidate single data cache line + BX lr + + +ArmCleanDataCacheEntryByMVA + MCR p15, 0, r0, c7, c10, 1 ; clean single data cache line + BX lr + + +ArmCleanInvalidateDataCacheEntryByMVA + MCR p15, 0, r0, c7, c14, 1 ; clean and invalidate single data cache line + BX lr + +ArmEnableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set I bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear I bit. + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmInvalidateInstructionCache + MOV R0,#0 + MCR p15,0,R0,c7,c5,0 ;Invalidate entire instruction cache + MOV R0,#0 + MCR p15,0,R0,c7,c10,4 ;Drain write buffer + BX LR + +ArmEnableMmu + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ArmDisableMmu + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + mov R0,#0 + mcr p15,0,R0,c7,c10,4 ;Drain write buffer + bx LR + +ArmEnableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmCleanDataCache + MRC p15,0,r15,c7,c10,3 + BNE ArmCleanDataCache + MOV R0,#0 + MCR p15,0,R0,c7,c10,4 ;Drain write buffer + BX LR + +ArmInvalidateDataCache + MOV R0,#0 + MCR p15,0,R0,c7,c6,0 ;Invalidate entire data cache + MOV R0,#0 + MCR p15,0,R0,c7,c10,4 ;Drain write buffer + BX LR + +ArmCleanInvalidateDataCache + MRC p15,0,r15,c7,c14,3 + BNE ArmCleanInvalidateDataCache + MOV R0,#0 + MCR p15,0,R0,c7,c10,4 ;Drain write buffer + BX LR + +ArmEnableBranchPrediction + bx LR ;Branch prediction is not supported. + +ArmDisableBranchPrediction + bx LR ;Branch prediction is not supported. + + END diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.c b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.c new file mode 100644 index 0000000000..4dfa18db58 --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.c @@ -0,0 +1,288 @@ +/** @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 <Chipset/Cortex-A8.h> +#include <Library/ArmLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include "ArmCortexALib.h" + +VOID +FillTranslationTable ( + IN UINT32 *TranslationTable, + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryRegion + ) +{ + UINT32 *Entry; + UINTN Sections; + UINTN Index; + UINT32 Attributes; + UINT32 PhysicalBase = MemoryRegion->PhysicalBase; + + switch (MemoryRegion->Attributes) { + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_BACK; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH: + Attributes = TT_DESCRIPTOR_SECTION_WRITE_THROUGH; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_DEVICE: + Attributes = TT_DESCRIPTOR_SECTION_DEVICE; + break; + case ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED: + default: + Attributes = TT_DESCRIPTOR_SECTION_UNCACHED; + break; + } + + Entry = TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(TranslationTable, MemoryRegion->VirtualBase); + Sections = MemoryRegion->Length / TT_DESCRIPTOR_SECTION_SIZE; + + for (Index = 0; Index < Sections; Index++) + { + *Entry++ = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(PhysicalBase) | Attributes; + PhysicalBase += TT_DESCRIPTOR_SECTION_SIZE; + } +} + +VOID +EFIAPI +ArmConfigureMmu ( + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable, + OUT VOID **TranslationTableBase OPTIONAL, + OUT UINTN *TranslationTableSize OPTIONAL + ) +{ + VOID *TranslationTable; + + // Allocate pages for translation table. + TranslationTable = AllocatePages(EFI_SIZE_TO_PAGES(TRANSLATION_TABLE_SIZE + TRANSLATION_TABLE_ALIGNMENT)); + TranslationTable = (VOID *)(((UINTN)TranslationTable + TRANSLATION_TABLE_ALIGNMENT_MASK) & ~TRANSLATION_TABLE_ALIGNMENT_MASK); + + if (TranslationTableBase != NULL) { + *TranslationTableBase = TranslationTable; + } + + if (TranslationTableBase != NULL) { + *TranslationTableSize = TRANSLATION_TABLE_SIZE; + } + + ZeroMem(TranslationTable, TRANSLATION_TABLE_SIZE); + + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + ArmInvalidateTlb(); + + ArmDisableDataCache(); + ArmDisableInstructionCache(); + ArmDisableMmu(); + + // Make sure nothing sneaked into the cache + ArmCleanInvalidateDataCache(); + ArmInvalidateInstructionCache(); + + while (MemoryTable->Length != 0) { + FillTranslationTable(TranslationTable, MemoryTable); + MemoryTable++; + } + + ArmSetTranslationTableBaseAddress(TranslationTable); + + ArmSetDomainAccessControl(DOMAIN_ACCESS_CONTROL_NONE(15) | + DOMAIN_ACCESS_CONTROL_NONE(14) | + DOMAIN_ACCESS_CONTROL_NONE(13) | + DOMAIN_ACCESS_CONTROL_NONE(12) | + DOMAIN_ACCESS_CONTROL_NONE(11) | + DOMAIN_ACCESS_CONTROL_NONE(10) | + DOMAIN_ACCESS_CONTROL_NONE( 9) | + DOMAIN_ACCESS_CONTROL_NONE( 8) | + DOMAIN_ACCESS_CONTROL_NONE( 7) | + DOMAIN_ACCESS_CONTROL_NONE( 6) | + DOMAIN_ACCESS_CONTROL_NONE( 5) | + DOMAIN_ACCESS_CONTROL_NONE( 4) | + DOMAIN_ACCESS_CONTROL_NONE( 3) | + DOMAIN_ACCESS_CONTROL_NONE( 2) | + DOMAIN_ACCESS_CONTROL_NONE( 1) | + DOMAIN_ACCESS_CONTROL_MANAGER(0)); + + ArmEnableInstructionCache(); + ArmEnableDataCache(); + ArmEnableMmu(); +} + +ARM_CACHE_TYPE +EFIAPI +ArmCacheType ( + VOID + ) +{ + return ARM_CACHE_TYPE_WRITE_BACK; +} + +ARM_CACHE_ARCHITECTURE +EFIAPI +ArmCacheArchitecture ( + VOID + ) +{ + return ARM_CACHE_ARCHITECTURE_SEPARATE; +} + +BOOLEAN +EFIAPI +ArmDataCachePresent ( + VOID + ) +{ + return TRUE; +} + +UINTN +EFIAPI +ArmDataCacheSize ( + VOID + ) +{ + return 16 * 1024; +} + +UINTN +EFIAPI +ArmDataCacheAssociativity ( + VOID + ) +{ + return 4; +} + +UINTN +ArmDataCacheSets ( + VOID + ) +{ + return 64; +} + +UINTN +EFIAPI +ArmDataCacheLineLength ( + VOID + ) +{ + return 64; +} + +BOOLEAN +EFIAPI +ArmInstructionCachePresent ( + VOID + ) +{ + return TRUE; +} + +UINTN +EFIAPI +ArmInstructionCacheSize ( + VOID + ) +{ + return 16 * 1024; +} + +UINTN +EFIAPI +ArmInstructionCacheAssociativity ( + VOID + ) +{ + return 4; +} + +UINTN +EFIAPI +ArmInstructionCacheLineLength ( + VOID + ) +{ + return 64; +} + +VOID +ArmCortexADataCacheOperation ( + IN ARM_CORTEX_A_CACHE_OPERATION DataCacheOperation + ) +{ + UINTN Set; + UINTN SetCount; + UINTN SetShift; + UINTN Way; + UINTN WayCount; + UINTN WayShift; + UINT32 SetWayFormat; + UINTN SavedInterruptState; + + SetCount = ArmDataCacheSets(); + WayCount = ArmDataCacheAssociativity(); + + // Cortex-A8 Manual, System Control Coprocessor chapter + SetShift = 6; + WayShift = 32 - LowBitSet32 ((UINT32)WayCount); + + SavedInterruptState = ArmDisableInterrupts(); + + for (Way = 0; Way < WayCount; Way++) { + for (Set = 0; Set < SetCount; Set++) { + // Build the format that the CP15 instruction can understand + SetWayFormat = (Way << WayShift) | (Set << SetShift); + + // Pass it through + (*DataCacheOperation)(SetWayFormat); + } + } + + ArmDrainWriteBuffer(); + + if (SavedInterruptState) { + ArmEnableInterrupts(); + } +} + +VOID +EFIAPI +ArmInvalidateDataCache ( + VOID + ) +{ + ArmCortexADataCacheOperation(ArmInvalidateDataCacheEntryBySetWay); +} + +VOID +EFIAPI +ArmCleanInvalidateDataCache ( + VOID + ) +{ + ArmCortexADataCacheOperation(ArmCleanInvalidateDataCacheEntryBySetWay); +} + +VOID +EFIAPI +ArmCleanDataCache ( + VOID + ) +{ + ArmCortexADataCacheOperation(ArmCleanDataCacheEntryBySetWay); +} diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.h b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.h new file mode 100644 index 0000000000..afe98bdfa2 --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexALib.h @@ -0,0 +1,45 @@ +/** @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 __ARMCORTEXALIB_H__ +#define __ARMCORTEXALIB_H__ + +typedef VOID (*ARM_CORTEX_A_CACHE_OPERATION)(UINT32); + +VOID +EFIAPI +ArmDrainWriteBuffer ( + VOID + ); + +VOID +EFIAPI +ArmInvalidateDataCacheEntryBySetWay ( + IN UINT32 SetWayFormat + ); + +VOID +EFIAPI +ArmCleanDataCacheEntryBySetWay ( + IN UINT32 SetWayFormat + ); + +VOID +EFIAPI +ArmCleanInvalidateDataCacheEntryBySetWay ( + IN UINT32 SetWayFormat + ); + +#endif // __ARMCORTEXALIB_H__ + diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.S b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.S new file mode 100644 index 0000000000..0e24f6341c --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.S @@ -0,0 +1,140 @@ +#------------------------------------------------------------------------------ +# +# 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 ASM_PFX(ArmInvalidateInstructionCache) +.globl ASM_PFX(ArmInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanDataCacheEntryByMVA) +.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA) +.globl ASM_PFX(ArmInvalidateDataCacheEntryBySetWay) +.globl ASM_PFX(ArmCleanDataCacheEntryBySetWay) +.globl ASM_PFX(ArmCleanInvalidateDataCacheEntryBySetWay) +.globl ASM_PFX(ArmDrainWriteBuffer) +.globl ASM_PFX(ArmEnableMmu) +.globl ASM_PFX(ArmDisableMmu) +.globl ASM_PFX(ArmEnableDataCache) +.globl ASM_PFX(ArmDisableDataCache) +.globl ASM_PFX(ArmEnableInstructionCache) +.globl ASM_PFX(ArmDisableInstructionCache) +.globl ASM_PFX(ArmEnableExtendPTConfig) +.globl ASM_PFX(ArmDisableExtendPTConfig) +.globl ASM_PFX(ArmEnableBranchPrediction) +.globl ASM_PFX(ArmDisableBranchPrediction) + +.set DC_ON, (0x1<<2) +.set IC_ON, (0x1<<12) +.set XP_ON, (0x1<<23) + +ASM_PFX(ArmInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c6, 1 @invalidate single data cache line + bx lr + + +ASM_PFX(ArmCleanDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c10, 1 @clean single data cache line + bx lr + + +ASM_PFX(ArmCleanInvalidateDataCacheEntryByMVA): + mcr p15, 0, r0, c7, c14, 1 @clean and invalidate single data cache line + bx lr + + +ASM_PFX(ArmInvalidateDataCacheEntryBySetWay): + mcr p15, 0, r0, c7, c6, 2 @ Invalidate this line + bx lr + + +ASM_PFX(ArmCleanInvalidateDataCacheEntryBySetWay): + mcr p15, 0, r0, c7, c14, 2 @ Clean and Invalidate this line + bx lr + + +ASM_PFX(ArmCleanDataCacheEntryBySetWay): + mcr p15, 0, r0, c7, c10, 2 @ Clean this line + bx lr + + +ASM_PFX(ArmDrainWriteBuffer): + mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer for sync + bx lr + + +ASM_PFX(ArmInvalidateInstructionCache): + mov R0,#0 + mcr p15,0,R0,c7,c5,0 @Invalidate entire instruction cache + mov R0,#0 + mcr p15,0,R0,c7,c5,4 @Instruction synchronization barrier + bx LR + +ASM_PFX(ArmEnableMmu): + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ASM_PFX(ArmDisableMmu): + mov R0,#0 + mcr p15,0,R0,c13,c0,0 @FCSE PID register must be cleared before disabling MMU + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 @Disable MMU + mov R0,#0 + mcr p15,0,R0,c7,c10,4 @Data synchronization barrier + mov R0,#0 + mcr p15,0,R0,c7,c5,4 @Instruction synchronization barrier + bx LR + +ASM_PFX(ArmEnableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableDataCache): + ldr R1,=DC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear C bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmEnableInstructionCache): + ldr R1,=IC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + orr R0,R0,R1 @Set I bit + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmDisableInstructionCache): + ldr R1,=IC_ON + mrc p15,0,R0,c1,c0,0 @Read control register configuration data + bic R0,R0,R1 @Clear I bit. + mcr p15,0,r0,c1,c0,0 @Write control register configuration data + bx LR + +ASM_PFX(ArmEnableBranchPrediction): + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ASM_PFX(ArmDisableBranchPrediction): + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.asm b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.asm new file mode 100644 index 0000000000..dbd8bd246a --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexASupport.asm @@ -0,0 +1,141 @@ +//------------------------------------------------------------------------------ +// +// 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 ArmInvalidateInstructionCache + EXPORT ArmInvalidateDataCacheEntryByMVA + EXPORT ArmCleanDataCacheEntryByMVA + EXPORT ArmCleanInvalidateDataCacheEntryByMVA + EXPORT ArmInvalidateDataCacheEntryBySetWay + EXPORT ArmCleanDataCacheEntryBySetWay + EXPORT ArmCleanInvalidateDataCacheEntryBySetWay + EXPORT ArmDrainWriteBuffer + EXPORT ArmEnableMmu + EXPORT ArmDisableMmu + EXPORT ArmEnableDataCache + EXPORT ArmDisableDataCache + EXPORT ArmEnableInstructionCache + EXPORT ArmDisableInstructionCache + EXPORT ArmEnableBranchPrediction + EXPORT ArmDisableBranchPrediction + +DC_ON EQU ( 0x1:SHL:2 ) +IC_ON EQU ( 0x1:SHL:12 ) +XP_ON EQU ( 0x1:SHL:23 ) + + + AREA ArmCacheLib, CODE, READONLY + PRESERVE8 + + +ArmInvalidateDataCacheEntryByMVA + MCR p15, 0, r0, c7, c6, 1 ; invalidate single data cache line + BX lr + + +ArmCleanDataCacheEntryByMVA + MCR p15, 0, r0, c7, c10, 1 ; clean single data cache line + BX lr + + +ArmCleanInvalidateDataCacheEntryByMVA + MCR p15, 0, r0, c7, c14, 1 ; clean and invalidate single data cache line + BX lr + + +ArmInvalidateDataCacheEntryBySetWay + mcr p15, 0, r0, c7, c6, 2 ; Invalidate this line + bx lr + + +ArmCleanInvalidateDataCacheEntryBySetWay + mcr p15, 0, r0, c7, c14, 2 ; Clean and Invalidate this line + bx lr + + +ArmCleanDataCacheEntryBySetWay + mcr p15, 0, r0, c7, c10, 2 ; Clean this line + bx lr + + +ArmDrainWriteBuffer + mcr p15, 0, r0, c7, c10, 4 ; Drain write buffer for sync + bx lr + + +ArmInvalidateInstructionCache + MOV R0,#0 + MCR p15,0,R0,c7,c5,0 ;Invalidate entire instruction cache + MOV R0,#0 + MCR p15,0,R0,c7,c5,4 ;Instruction synchronization barrier + BX LR + +ArmEnableMmu + mrc p15,0,R0,c1,c0,0 + orr R0,R0,#1 + mcr p15,0,R0,c1,c0,0 + bx LR + +ArmDisableMmu + mov R0,#0 + mcr p15,0,R0,c13,c0,0 ;FCSE PID register must be cleared before disabling MMU + mrc p15,0,R0,c1,c0,0 + bic R0,R0,#1 + mcr p15,0,R0,c1,c0,0 ;Disable MMU + mov R0,#0 + mcr p15,0,R0,c7,c10,4 ;Data synchronization barrier + mov R0,#0 + mcr p15,0,R0,c7,c5,4 ;Instruction synchronization barrier + bx LR + +ArmEnableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableDataCache + LDR R1,=DC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear C bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmEnableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + ORR R0,R0,R1 ;Set I bit + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmDisableInstructionCache + LDR R1,=IC_ON + MRC p15,0,R0,c1,c0,0 ;Read control register configuration data + BIC R0,R0,R1 ;Clear I bit. + MCR p15,0,r0,c1,c0,0 ;Write control register configuration data + BX LR + +ArmEnableBranchPrediction + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + +ArmDisableBranchPrediction + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00000800 + mcr p15, 0, r0, c1, c0, 0 + bx LR + + END diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf new file mode 100644 index 0000000000..54b77e31b4 --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf @@ -0,0 +1,31 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmCortexArmLib
+ FILE_GUID = 411cdfd8-f964-4b9d-a3e3-1719a9c15559
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ../Common/ArmLibSupport.S | GCC
+ ../Common/ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ ArmCortexASupport.S | GCC
+ ArmCortexASupport.asm | RVCT
+
+ ArmCortexALib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf new file mode 100644 index 0000000000..450dfe5936 --- /dev/null +++ b/ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf @@ -0,0 +1,31 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmCortexArmLibPrePi
+ FILE_GUID = A150FA0C-F4E8-4207-9BEB-CD6DFB430D73
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ../Common/ArmLibSupport.S | GCC
+ ../Common/ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ ArmCortexASupport.S | GCC
+ ArmCortexASupport.asm | RVCT
+
+ ArmCortexALib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ PrePiLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/ArmLib/Common/ArmLib.c b/ArmPkg/Library/ArmLib/Common/ArmLib.c new file mode 100644 index 0000000000..b015dc4aa1 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Common/ArmLib.c @@ -0,0 +1,60 @@ +/** @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 <Base.h>
+
+#include <Library/ArmLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include "ArmLibPrivate.h"
+
+VOID
+EFIAPI
+ArmCacheInformation (
+ OUT ARM_CACHE_INFO *CacheInfo
+ )
+{
+ if (CacheInfo != NULL) {
+ CacheInfo->Type = ArmCacheType();
+ CacheInfo->Architecture = ArmCacheArchitecture();
+ CacheInfo->DataCachePresent = ArmDataCachePresent();
+ CacheInfo->DataCacheSize = ArmDataCacheSize();
+ CacheInfo->DataCacheAssociativity = ArmDataCacheAssociativity();
+ CacheInfo->DataCacheLineLength = ArmDataCacheLineLength();
+ CacheInfo->InstructionCachePresent = ArmInstructionCachePresent();
+ CacheInfo->InstructionCacheSize = ArmInstructionCacheSize();
+ CacheInfo->InstructionCacheAssociativity = ArmInstructionCacheAssociativity();
+ CacheInfo->InstructionCacheLineLength = ArmInstructionCacheLineLength();
+ }
+}
+
+VOID
+EFIAPI
+ArmSwitchProcessorMode (
+ IN ARM_PROCESSOR_MODE Mode
+ )
+{
+ CPSRMaskInsert(ARM_PROCESSOR_MODE_MASK, Mode);
+}
+
+
+ARM_PROCESSOR_MODE
+EFIAPI
+ArmProcessorMode (
+ VOID
+ )
+{
+ return (ARM_PROCESSOR_MODE)(CPSRRead() & (UINT32)ARM_PROCESSOR_MODE_MASK);
+}
diff --git a/ArmPkg/Library/ArmLib/Common/ArmLibPrivate.h b/ArmPkg/Library/ArmLib/Common/ArmLibPrivate.h new file mode 100644 index 0000000000..d1d2523947 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Common/ArmLibPrivate.h @@ -0,0 +1,70 @@ +/** @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 __ARM_LIB_PRIVATE_H__
+#define __ARM_LIB_PRIVATE_H__
+
+#define CACHE_SIZE_4_KB (3UL)
+#define CACHE_SIZE_8_KB (4UL)
+#define CACHE_SIZE_16_KB (5UL)
+#define CACHE_SIZE_32_KB (6UL)
+#define CACHE_SIZE_64_KB (7UL)
+#define CACHE_SIZE_128_KB (8UL)
+
+#define CACHE_ASSOCIATIVITY_DIRECT (0UL)
+#define CACHE_ASSOCIATIVITY_4_WAY (2UL)
+#define CACHE_ASSOCIATIVITY_8_WAY (3UL)
+
+#define CACHE_PRESENT (0UL)
+#define CACHE_NOT_PRESENT (1UL)
+
+#define CACHE_LINE_LENGTH_32_BYTES (2UL)
+
+#define SIZE_FIELD_TO_CACHE_SIZE(x) (((x) >> 6) & 0x0F)
+#define SIZE_FIELD_TO_CACHE_ASSOCIATIVITY(x) (((x) >> 3) & 0x07)
+#define SIZE_FIELD_TO_CACHE_PRESENCE(x) (((x) >> 2) & 0x01)
+#define SIZE_FIELD_TO_CACHE_LINE_LENGTH(x) (((x) >> 0) & 0x03)
+
+#define DATA_CACHE_SIZE_FIELD(x) (((x) >> 12) & 0x0FFF)
+#define INSTRUCTION_CACHE_SIZE_FIELD(x) (((x) >> 0) & 0x0FFF)
+
+#define DATA_CACHE_SIZE(x) (SIZE_FIELD_TO_CACHE_SIZE(DATA_CACHE_SIZE_FIELD(x)))
+#define DATA_CACHE_ASSOCIATIVITY(x) (SIZE_FIELD_TO_CACHE_ASSOCIATIVITY(DATA_CACHE_SIZE_FIELD(x)))
+#define DATA_CACHE_PRESENT(x) (SIZE_FIELD_TO_CACHE_PRESENCE(DATA_CACHE_SIZE_FIELD(x)))
+#define DATA_CACHE_LINE_LENGTH(x) (SIZE_FIELD_TO_CACHE_LINE_LENGTH(DATA_CACHE_SIZE_FIELD(x)))
+
+#define INSTRUCTION_CACHE_SIZE(x) (SIZE_FIELD_TO_CACHE_SIZE(INSTRUCTION_CACHE_SIZE_FIELD(x)))
+#define INSTRUCTION_CACHE_ASSOCIATIVITY(x) (SIZE_FIELD_TO_CACHE_ASSOCIATIVITY(INSTRUCTION_CACHE_SIZE_FIELD(x)))
+#define INSTRUCTION_CACHE_PRESENT(x) (SIZE_FIELD_TO_CACHE_PRESENCE(INSTRUCTION_CACHE_SIZE_FIELD(x)))
+#define INSTRUCTION_CACHE_LINE_LENGTH(x) (SIZE_FIELD_TO_CACHE_LINE_LENGTH(INSTRUCTION_CACHE_SIZE_FIELD(x)))
+
+#define CACHE_TYPE(x) (((x) >> 25) & 0x0F)
+#define CACHE_TYPE_WRITE_BACK (0x0EUL)
+
+#define CACHE_ARCHITECTURE(x) (((x) >> 24) & 0x01)
+#define CACHE_ARCHITECTURE_UNIFIED (0UL)
+#define CACHE_ARCHITECTURE_SEPARATE (1UL)
+
+VOID
+CPSRMaskInsert (
+ IN UINT32 Mask,
+ IN UINT32 Value
+ );
+
+UINT32
+CPSRRead (
+ VOID
+ );
+
+#endif // __ARM_LIB_PRIVATE_H__
diff --git a/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S new file mode 100644 index 0000000000..d80100c788 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.S @@ -0,0 +1,89 @@ +#------------------------------------------------------------------------------ +# +# 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 ASM_PFX(Cp15IdCode) +.globl ASM_PFX(Cp15CacheInfo) +.globl ASM_PFX(ArmEnableInterrupts) +.globl ASM_PFX(ArmDisableInterrupts) +.globl ASM_PFX(ArmGetInterruptState) +.globl ASM_PFX(ArmInvalidateTlb) +.globl ASM_PFX(ArmSetTranslationTableBaseAddress) +.globl ASM_PFX(ArmSetDomainAccessControl) +.globl ASM_PFX(CPSRMaskInsert) +.globl ASM_PFX(CPSRRead) + +#------------------------------------------------------------------------------ + +ASM_PFX(Cp15IdCode): + mrc p15,0,R0,c0,c0,0 + bx LR + +ASM_PFX(Cp15CacheInfo): + mrc p15,0,R0,c0,c0,1 + bx LR + +ASM_PFX(ArmEnableInterrupts): + mrs R0,CPSR + bic R0,R0,#0x80 @Enable IRQ interrupts + msr CPSR_c,R0 + bx LR + +ASM_PFX(ArmDisableInterrupts): + mrs R0,CPSR + orr R1,R0,#0x80 @Disable IRQ interrupts + msr CPSR_c,R1 + tst R0,#0x80 + moveq R0,#1 + movne R0,#0 + bx LR + +ASM_PFX(ArmGetInterruptState): + mrs R0,CPSR + tst R0,#0x80 @Check if IRQ is enabled. + moveq R0,#1 + movne R0,#0 + bx LR + +ASM_PFX(ArmInvalidateTlb): + mov r0,#0 + mcr p15,0,r0,c8,c7,0 + bx lr + +ASM_PFX(ArmSetTranslationTableBaseAddress): + mcr p15,0,r0,c2,c0,0 + bx lr + +ASM_PFX(ArmSetDomainAccessControl): + mcr p15,0,r0,c3,c0,0 + bx lr + +ASM_PFX(CPSRMaskInsert): @ on entry, r0 is the mask and r1 is the field to insert + stmfd sp!, {r4-r12, lr} @ save all the banked registers + mov r3, sp @ copy the stack pointer into a non-banked register + mrs r2, cpsr @ read the cpsr + bic r2, r2, r0 @ clear mask in the cpsr + and r1, r1, r0 @ clear bits outside the mask in the input + orr r2, r2, r1 @ set field + msr cpsr_cxsf, r2 @ write back cpsr (may have caused a mode switch) + mov sp, r3 @ restore stack pointer + ldmfd sp!, {r4-r12, lr} @ restore registers + bx lr @ return (hopefully thumb-safe!) + +ASM_PFX(CPSRRead): + mrs r0, cpsr + bx lr + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm new file mode 100644 index 0000000000..ec7db638af --- /dev/null +++ b/ArmPkg/Library/ArmLib/Common/ArmLibSupport.asm @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// 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 Cp15IdCode + EXPORT Cp15CacheInfo + EXPORT ArmEnableInterrupts + EXPORT ArmDisableInterrupts + EXPORT ArmGetInterruptState + EXPORT ArmInvalidateTlb + EXPORT ArmSetTranslationTableBaseAddress + EXPORT ArmSetDomainAccessControl + EXPORT CPSRMaskInsert + EXPORT CPSRRead + + AREA ArmLibSupport, CODE, READONLY + +Cp15IdCode + mrc p15,0,R0,c0,c0,0 + bx LR + +Cp15CacheInfo + mrc p15,0,R0,c0,c0,1 + bx LR + +ArmEnableInterrupts + mrs R0,CPSR + bic R0,R0,#0x80 ;Enable IRQ interrupts + msr CPSR_c,R0 + bx LR + +ArmDisableInterrupts + mrs R0,CPSR + orr R1,R0,#0x80 ;Disable IRQ interrupts + msr CPSR_c,R1 + tst R0,#0x80 + moveq R0,#1 + movne R0,#0 + bx LR + +ArmGetInterruptState + mrs R0,CPSR + tst R0,#0x80 ;Check if IRQ is enabled. + moveq R0,#1 + movne R0,#0 + bx LR + +ArmInvalidateTlb + mov r0,#0 + mcr p15,0,r0,c8,c7,0 + bx lr + +ArmSetTranslationTableBaseAddress + mcr p15,0,r0,c2,c0,0 + bx lr + +ArmSetDomainAccessControl + mcr p15,0,r0,c3,c0,0 + bx lr + +CPSRMaskInsert ; on entry, r0 is the mask and r1 is the field to insert + stmfd sp!, {r4-r12, lr} ; save all the banked registers + mov r3, sp ; copy the stack pointer into a non-banked register + mrs r2, cpsr ; read the cpsr + bic r2, r2, r0 ; clear mask in the cpsr + and r1, r1, r0 ; clear bits outside the mask in the input + orr r2, r2, r1 ; set field + msr cpsr_cxsf, r2 ; write back cpsr (may have caused a mode switch) + mov sp, r3 ; restore stack pointer + ldmfd sp!, {r4-r12, lr} ; restore registers + bx lr ; return (hopefully thumb-safe!) + +CPSRRead + mrs r0, cpsr + bx lr + + END + + diff --git a/ArmPkg/Library/ArmLib/Null/NullArmCacheInformation.c b/ArmPkg/Library/ArmLib/Null/NullArmCacheInformation.c new file mode 100644 index 0000000000..08a1ad0c5f --- /dev/null +++ b/ArmPkg/Library/ArmLib/Null/NullArmCacheInformation.c @@ -0,0 +1,106 @@ +/** @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 <Library/ArmLib.h>
+#include "ArmLibPrivate.h"
+
+ARM_CACHE_TYPE
+EFIAPI
+ArmCacheType (
+ VOID
+ )
+{
+ return ARM_CACHE_TYPE_UNKNOWN;
+}
+
+ARM_CACHE_ARCHITECTURE
+EFIAPI
+ArmCacheArchitecture (
+ VOID
+ )
+{
+ return ARM_CACHE_ARCHITECTURE_UNKNOWN;
+}
+
+BOOLEAN
+EFIAPI
+ArmDataCachePresent (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+UINTN
+EFIAPI
+ArmDataCacheSize (
+ VOID
+ )
+{
+ return 0;
+}
+
+UINTN
+EFIAPI
+ArmDataCacheAssociativity (
+ VOID
+ )
+{
+ return 0;
+}
+
+UINTN
+EFIAPI
+ArmDataCacheLineLength (
+ VOID
+ )
+{
+ return 0;
+}
+
+BOOLEAN
+EFIAPI
+ArmInstructionCachePresent (
+ VOID
+ )
+{
+ return FALSE;
+}
+
+UINTN
+EFIAPI
+ArmInstructionCacheSize (
+ VOID
+ )
+{
+ return 0;
+}
+
+UINTN
+EFIAPI
+ArmInstructionCacheAssociativity (
+ VOID
+ )
+{
+ return 0;
+}
+
+UINTN
+EFIAPI
+ArmInstructionCacheLineLength (
+ VOID
+ )
+{
+ return 0;
+}
diff --git a/ArmPkg/Library/ArmLib/Null/NullArmLib.c b/ArmPkg/Library/ArmLib/Null/NullArmLib.c new file mode 100644 index 0000000000..6e95cba706 --- /dev/null +++ b/ArmPkg/Library/ArmLib/Null/NullArmLib.c @@ -0,0 +1,117 @@ +/** @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/ArmLib.h>
+#include <Library/DebugLib.h>
+
+VOID
+EFIAPI
+ArmCleanInvalidateDataCache (
+ VOID
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+ArmCleanDataCache (
+ VOID
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+ArmInvalidateInstructionCache (
+ VOID
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+ArmInvalidateDataCacheEntryByMVA (
+ IN UINTN Address
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+ArmCleanDataCacheEntryByMVA (
+ IN UINTN Address
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+ArmCleanInvalidateDataCacheEntryByMVA (
+ IN UINTN Address
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+ArmEnableDataCache (
+ VOID
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+ArmDisableDataCache (
+ VOID
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+ArmEnableInstructionCache (
+ VOID
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
+
+VOID
+EFIAPI
+ArmDisableInstructionCache (
+ VOID
+ )
+{
+ // Do not run code using the Null cache library.
+ ASSERT(FALSE);
+}
diff --git a/ArmPkg/Library/ArmLib/Null/NullArmLib.inf b/ArmPkg/Library/ArmLib/Null/NullArmLib.inf new file mode 100644 index 0000000000..ff31b9cecb --- /dev/null +++ b/ArmPkg/Library/ArmLib/Null/NullArmLib.inf @@ -0,0 +1,26 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = NullArmLib
+ FILE_GUID = 00586300-0E06-4790-AC44-86C56ACBB942
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmLib
+
+[Sources.common]
+ ../Common/ArmLibSupport.S | GCC
+ ../Common/ArmLibSupport.asm | RVCT
+ ../Common/ArmLib.c
+
+ NullArmLib.c
+ NullArmCacheInformation.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmCacheOperationThreshold
diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/Llvm_int_lib.h b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/Llvm_int_lib.h new file mode 100644 index 0000000000..e2c00a2033 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/Llvm_int_lib.h @@ -0,0 +1,83 @@ +/** @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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include <Base.h> +#include <Library/DebugLib.h> + +#define CHAR_BIT 8 + +typedef union { + INT64 all; + struct { + UINT32 low; + INT32 high; + }; +} dwords; + +typedef union { + UINT64 all; + struct { + UINT32 low; + UINT32 high; + }; +} udwords; + +#if __GNUC__ + #define COUNT_LEADING_ZEROS(_a) __builtin_clz((_a)) + #define COUNT_TRAILING_ZEROS(_a) __builtin_ctz((_a)) +#else +#error COUNT_LEADING_ZEROS() and COUNT_TRAILING_ZEROS() macros not ported to your compiler +#endif diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S new file mode 100644 index 0000000000..ac2bdbafd0 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.S @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# +# 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 ___ashldi3 +___ashldi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + cmp r2, #31 + @ lr needed for prologue + bls L2 + cmp r2, #63 + subls r2, r2, #32 + movls r2, r0, asl r2 + movhi r2, #0 + mov r1, r2 + mov r0, #0 + bx lr +L2: + cmp r2, #0 + rsbne r3, r2, #32 + movne r3, r0, lsr r3 + movne r0, r0, asl r2 + orrne r1, r3, r1, asl r2 + bx lr diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.c new file mode 100644 index 0000000000..f708737035 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashldi3.c @@ -0,0 +1,83 @@ +/** @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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include "Llvm_int_lib.h" + +// Returns: a << b + +// Precondition: 0 <= b < bits_in_dword + +INT64 +__ashldi3(INT64 a, INT32 b) +{ + const int bits_in_word = (int)(sizeof(INT32) * CHAR_BIT); + dwords input; + dwords result; + input.all = a; + if (b & bits_in_word) // bits_in_word <= b < bits_in_dword + { + result.low = 0; + result.high = input.low << (b - bits_in_word); + } + else // 0 <= b < bits_in_word + { + if (b == 0) + return a; + result.low = input.low << b; + result.high = (input.high << b) | (input.low >> (bits_in_word - b)); + } + return result.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S new file mode 100644 index 0000000000..fb87c88a09 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.S @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# 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 ___ashrdi3 +___ashrdi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + cmp r2, #31 + @ lr needed for prologue + bls L2 + cmp r2, #63 + subls r2, r2, #32 + mov ip, r1, asr #31 + movls r2, r1, asr r2 + movhi r2, ip + mov r0, r2 + mov r1, ip + bx lr +L2: + cmp r2, #0 + rsbne r3, r2, #32 + movne r3, r1, asl r3 + movne r1, r1, asr r2 + orrne r0, r3, r0, lsr r2 + bx lr diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.c new file mode 100644 index 0000000000..ce5134eb64 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ashrdi3.c @@ -0,0 +1,84 @@ +/** @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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include "Llvm_int_lib.h" + +// Returns: arithmetic a >> b + +// Precondition: 0 <= b < bits_in_dword + +INT64 +__ashrdi3(INT64 a, INT32 b) +{ + const int bits_in_word = (int)(sizeof(INT32) * CHAR_BIT); + dwords input; + dwords result; + input.all = a; + if (b & bits_in_word) // bits_in_word <= b < bits_in_dword + { + // result.high = input.high < 0 ? -1 : 0 + result.high = input.high >> (bits_in_word - 1); + result.low = input.high >> (b - bits_in_word); + } + else // 0 <= b < bits_in_word + { + if (b == 0) + return a; + result.high = input.high >> b; + result.low = (input.high << (bits_in_word - b)) | (input.low >> b); + } + return result.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.c new file mode 100644 index 0000000000..c7b4607ca4 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/clzsi2.c @@ -0,0 +1,96 @@ +/** @file + Compiler intrinsic to return the number of leading zeros, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +// Returns: the number of leading 0-bits + +// Precondition: a != 0 + +INT32 +__clzsi2(INT32 a) +{ + UINT32 x = (UINT32)a; + INT32 t = ((x & 0xFFFF0000) == 0) << 4; // if (x is small) t = 16 else 0 + x >>= 16 - t; // x = [0 - 0xFFFF] + UINT32 r = t; // r = [0, 16] + // return r + clz(x) + t = ((x & 0xFF00) == 0) << 3; + x >>= 8 - t; // x = [0 - 0xFF] + r += t; // r = [0, 8, 16, 24] + // return r + clz(x) + t = ((x & 0xF0) == 0) << 2; + x >>= 4 - t; // x = [0 - 0xF] + r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28] + // return r + clz(x) + t = ((x & 0xC) == 0) << 1; + x >>= 2 - t; // x = [0 - 3] + r += t; // r = [0 - 30] and is even + // return r + clz(x) +// switch (x) +// { +// case 0: +// return r + 2; +// case 1: +// return r + 1; +// case 2: +// case 3: +// return r; +// } + return r + ((2 - x) & -((x & 2) == 0)); +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.c new file mode 100644 index 0000000000..c0e18977ec --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ctzsi2.c @@ -0,0 +1,111 @@ +/** @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 + Compiler intrinsic to return the number of trailing zeros, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +// Returns: the number of trailing 0-bits + +// Precondition: a != 0 + +INT32 +__ctzsi2(INT32 a) +{ + UINT32 x = (UINT32)a; + INT32 t = ((x & 0x0000FFFF) == 0) << 4; // if (x has no small bits) t = 16 else 0 + x >>= t; // x = [0 - 0xFFFF] + higher garbage bits + UINT32 r = t; // r = [0, 16] + // return r + ctz(x) + t = ((x & 0x00FF) == 0) << 3; + x >>= t; // x = [0 - 0xFF] + higher garbage bits + r += t; // r = [0, 8, 16, 24] + // return r + ctz(x) + t = ((x & 0x0F) == 0) << 2; + x >>= t; // x = [0 - 0xF] + higher garbage bits + r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28] + // return r + ctz(x) + t = ((x & 0x3) == 0) << 1; + x >>= t; + x &= 3; // x = [0 - 3] + r += t; // r = [0 - 30] and is even + // return r + ctz(x) +// The branch-less return statement below is equivalent +// to the following switch statement: +// switch (x) +// { +// case 0: +// return r + 2; +// case 2: +// return r + 1; +// case 1: +// case 3: +// return r; +// } + return r + ((2 - (x >> 1)) & -((x & 1) == 0)); +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.asm new file mode 100644 index 0000000000..f6f9bc2d56 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/div.asm @@ -0,0 +1,155 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_uidiv + EXPORT __aeabi_uidivmod + EXPORT __aeabi_idiv + EXPORT __aeabi_idivmod + + AREA Math, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_uidivmode ( +; IN UINT32 Dividen +; IN UINT32 Divisor +; ); +; + +__aeabi_uidiv +__aeabi_uidivmod + RSBS r12, r1, r0, LSR #4 + MOV r2, #0 + BCC __arm_div4 + RSBS r12, r1, r0, LSR #8 + BCC __arm_div8 + MOV r3, #0 + B __arm_div_large + +; +;INT32 +;EFIAPI +;__aeabi_idivmode ( +; IN INT32 Dividen +; IN INT32 Divisor +; ); +; +__aeabi_idiv +__aeabi_idivmod + ORRS r12, r0, r1 + BMI __arm_div_negative + RSBS r12, r1, r0, LSR #1 + MOV r2, #0 + BCC __arm_div1 + RSBS r12, r1, r0, LSR #4 + BCC __arm_div4 + RSBS r12, r1, r0, LSR #8 + BCC __arm_div8 + MOV r3, #0 + B __arm_div_large +__arm_div8 + RSBS r12, r1, r0, LSR #7 + SUBCS r0, r0, r1, LSL #7 + ADC r2, r2, r2 + RSBS r12, r1, r0,LSR #6 + SUBCS r0, r0, r1, LSL #6 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #5 + SUBCS r0, r0, r1, LSL #5 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #4 + SUBCS r0, r0, r1, LSL #4 + ADC r2, r2, r2 +__arm_div4 + RSBS r12, r1, r0, LSR #3 + SUBCS r0, r0, r1, LSL #3 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #2 + SUBCS r0, r0, r1, LSL #2 + ADCS r2, r2, r2 + RSBS r12, r1, r0, LSR #1 + SUBCS r0, r0, r1, LSL #1 + ADC r2, r2, r2 +__arm_div1 + SUBS r1, r0, r1 + MOVCC r1, r0 + ADC r0, r2, r2 + BX r14 +__arm_div_negative + ANDS r2, r1, #0x80000000 + RSBMI r1, r1, #0 + EORS r3, r2, r0, ASR #32 + RSBCS r0, r0, #0 + RSBS r12, r1, r0, LSR #4 + BCC label1 + RSBS r12, r1, r0, LSR #8 + BCC label2 +__arm_div_large + LSL r1, r1, #6 + RSBS r12, r1, r0, LSR #8 + ORR r2, r2, #0xfc000000 + BCC label2 + LSL r1, r1, #6 + RSBS r12, r1, r0, LSR #8 + ORR r2, r2, #0x3f00000 + BCC label2 + LSL r1, r1, #6 + RSBS r12, r1, r0, LSR #8 + ORR r2, r2, #0xfc000 + ORRCS r2, r2, #0x3f00 + LSLCS r1, r1, #6 + RSBS r12, r1, #0 + BCS __aeabi_idiv0 +label3 + LSRCS r1, r1, #6 +label2 + RSBS r12, r1, r0, LSR #7 + SUBCS r0, r0, r1, LSL #7 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #6 + SUBCS r0, r0, r1, LSL #6 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #5 + SUBCS r0, r0, r1, LSL #5 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #4 + SUBCS r0, r0, r1, LSL #4 + ADC r2, r2, r2 +label1 + RSBS r12, r1, r0, LSR #3 + SUBCS r0, r0, r1, LSL #3 + ADC r2, r2, r2 + RSBS r12, r1, r0, LSR #2 + SUBCS r0, r0, r1, LSL #2 + ADCS r2, r2, r2 + BCS label3 + RSBS r12, r1, r0, LSR #1 + SUBCS r0, r0, r1, LSL #1 + ADC r2, r2, r2 + SUBS r1, r0, r1 + MOVCC r1, r0 + ADC r0, r2, r2 + ASRS r3, r3, #31 + RSBMI r0, r0, #0 + RSBCS r1, r1, #0 + BX r14 + + ; What to do about division by zero? For now, just return. +__aeabi_idiv0 + BX r14 + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S new file mode 100644 index 0000000000..b7d946ecc7 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.S @@ -0,0 +1,48 @@ +#------------------------------------------------------------------------------ +# +# 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 ___divdi3 +___divdi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r7, lr} + mov r4, r3, asr #31 + add r7, sp, #8 + stmfd sp!, {r10, r11} + mov r10, r1, asr #31 + sub sp, sp, #8 + mov r11, r10 + mov r5, r4 + eor r0, r0, r10 + eor r1, r1, r10 + eor r2, r2, r4 + eor r3, r3, r4 + subs r2, r2, r4 + sbc r3, r3, r5 + mov ip, #0 + subs r0, r0, r10 + sbc r1, r1, r11 + str ip, [sp, #0] + bl ___udivmoddi4 + eor r2, r10, r4 + eor r3, r10, r4 + eor r0, r0, r2 + eor r1, r1, r3 + subs r0, r0, r2 + sbc r1, r1, r3 + sub sp, r7, #16 + ldmfd sp!, {r10, r11} + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.c new file mode 100644 index 0000000000..286a504b49 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divdi3.c @@ -0,0 +1,77 @@ +/** @file + Compiler intrinsic for 64-bit compare, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT64 __udivmoddi4(UINT64 a, UINT64 b, UINT64* rem); + +// Returns: a / b + +INT64 +__divdi3(INT64 a, INT64 b) +{ + const int bits_in_dword_m1 = (int)(sizeof(INT64) * CHAR_BIT) - 1; + INT64 s_a = a >> bits_in_dword_m1; // s_a = a < 0 ? -1 : 0 + INT64 s_b = b >> bits_in_dword_m1; // s_b = b < 0 ? -1 : 0 + a = (a ^ s_a) - s_a; // negate if s_a == -1 + b = (b ^ s_b) - s_b; // negate if s_b == -1 + s_a ^= s_b; // sign of quotient + return (__udivmoddi4(a, b, (UINT64*)0) ^ s_a) - s_a; // negate if s_a == -1 +} + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S new file mode 100644 index 0000000000..2651572222 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.S @@ -0,0 +1,33 @@ +#------------------------------------------------------------------------------ +# +# 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 ___divsi3 +___divsi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + eor r3, r0, r0, asr #31 + eor r2, r1, r1, asr #31 + stmfd sp!, {r4, r5, r7, lr} + mov r5, r0, asr #31 + add r7, sp, #8 + mov r4, r1, asr #31 + sub r0, r3, r0, asr #31 + sub r1, r2, r1, asr #31 + bl ___udivsi3 + eor r1, r5, r4 + eor r0, r0, r1 + rsb r0, r1, r0 + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.c new file mode 100644 index 0000000000..56d731ca8e --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/divsi3.c @@ -0,0 +1,78 @@ +/** @file + Compiler intrinsic for 32--bit unsigned division, ported from LLVM code. + + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT32 __udivsi3(UINT32 n, UINT32 d); + +// Returns: a / b + +INT32 +__divsi3(INT32 a, INT32 b) +{ + const int bits_in_word_m1 = (int)(sizeof(INT32) * CHAR_BIT) - 1; + INT32 s_a = a >> bits_in_word_m1; // s_a = a < 0 ? -1 : 0 + INT32 s_b = b >> bits_in_word_m1; // s_b = b < 0 ? -1 : 0 + a = (a ^ s_a) - s_a; // negate if s_a == -1 + b = (b ^ s_b) - s_b; // negate if s_b == -1 + s_a ^= s_b; // sign of quotient + return (__udivsi3(a, b) ^ s_a) - s_a; // negate if s_a == -1 +} + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lasr.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lasr.asm new file mode 100644 index 0000000000..9956d064c2 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lasr.asm @@ -0,0 +1,41 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_lasr + + AREA Math, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_lasr ( +; IN UINT32 Dividen +; IN UINT32 Divisor +; ); +; +__aeabi_lasr + SUBS r3,r2,#0x20 + BPL {pc} + 0x18 ; 0x1c + RSB r3,r2,#0x20 + LSR r0,r0,r2 + ORR r0,r0,r1,LSL r3 + ASR r1,r1,r2 + BX lr + ASR r0,r1,r3 + ASR r1,r1,#31 + BX lr + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.asm new file mode 100644 index 0000000000..cb81608b01 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ldivmod.asm @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_ldivmod + EXTERN __aeabi_uldivmod + + AREA Math, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_uidivmode ( +; IN UINT32 Dividen +; IN UINT32 Divisor +; ); +; + +__aeabi_ldivmod + PUSH {r4,lr} + ASRS r4,r1,#1 + EOR r4,r4,r3,LSR #1 + BPL {pc} + 0xc ; 0x18 + RSBS r0,r0,#0 + RSC r1,r1,#0 + TST r3,r3 + BPL {pc} + 0xc ; 0x28 + RSBS r2,r2,#0 + RSC r3,r3,#0 + BL __aeabi_uldivmod ; + TST r4,#0x40000000 + BEQ {pc} + 0xc ; 0x3c + RSBS r0,r0,#0 + RSC r1,r1,#0 + TST r4,#0x80000000 + BEQ {pc} + 0xc ; 0x4c + RSBS r2,r2,#0 + RSC r3,r3,#0 + POP {r4,pc} + + END + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsl.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsl.asm new file mode 100644 index 0000000000..745b984085 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsl.asm @@ -0,0 +1,43 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_llsl + + AREA Math, CODE, READONLY + +; +;VOID +;EFIAPI +;__aeabi_llsl ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINT32 Size +; ); +; + +__aeabi_llsl + SUBS r3,r2,#0x20 + BPL {pc} + 0x18 ; 0x1c + RSB r3,r2,#0x20 + LSL r1,r1,r2 + ORR r1,r1,r0,LSR r3 + LSL r0,r0,r2 + BX lr + LSL r1,r0,r3 + MOV r0,#0 + BX lr + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsr.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsr.asm new file mode 100644 index 0000000000..630b542c70 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/llsr.asm @@ -0,0 +1,44 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_llsr + + AREA Math, CODE, READONLY + +; +;VOID +;EFIAPI +;__aeabi_llsr ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINT32 Size +; ); +; +__aeabi_llsr + SUBS r3,r2,#0x20 + BPL {pc} + 0x18 ; 0x1c + RSB r3,r2,#0x20 + LSR r0,r0,r2 + ORR r0,r0,r1,LSL r3 + LSR r1,r1,r2 + BX lr + LSR r0,r1,r3 + MOV r1,#0 + BX lr + + END + + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S new file mode 100644 index 0000000000..2257deef97 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.S @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# +# 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 ___lshrdi3 +___lshrdi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 0, uses_anonymous_args = 0 + @ link register save eliminated. + cmp r2, #31 + @ lr needed for prologue + bls L2 + cmp r2, #63 + subls r2, r2, #32 + movls r2, r1, lsr r2 + movhi r2, #0 + mov r0, r2 + mov r1, #0 + bx lr +L2: + cmp r2, #0 + rsbne r3, r2, #32 + movne r3, r1, asl r3 + movne r1, r1, lsr r2 + orrne r0, r3, r0, lsr r2 + bx lr diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.c new file mode 100644 index 0000000000..14b3c8f00a --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/lshrdi3.c @@ -0,0 +1,83 @@ +/** @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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include "Llvm_int_lib.h" + +// Returns: logical a >> b + +// Precondition: 0 <= b < bits_in_dword + +INT64 +__lshrdi3(INT64 a, INT32 b) +{ + const int bits_in_word = (int)(sizeof(INT32) * CHAR_BIT); + udwords input; + udwords result; + input.all = a; + if (b & bits_in_word) // bits_in_word <= b < bits_in_dword + { + result.high = 0; + result.low = input.high >> (b - bits_in_word); + } + else // 0 <= b < bits_in_word + { + if (b == 0) + return a; + result.high = input.high >> b; + result.low = (input.high << (bits_in_word - b)) | (input.low >> b); + } + return result.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S new file mode 100644 index 0000000000..2582a81f90 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.S @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------------ +# +# 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 _memcpy +_memcpy: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r7, lr} + mov ip, #0 + add r7, sp, #0 + mov lr, r0 + b L4 +L5: + ldrb r3, [r1], #1 @ zero_extendqisi2 + add ip, ip, #1 + and r3, r3, #255 + strb r3, [lr], #1 +L4: + cmp ip, r2 + bne L5 + ldmfd sp!, {r7, pc} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.asm new file mode 100644 index 0000000000..60dbcf2ab5 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy.asm @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_memcpy + + AREA Memcpy, CODE, READONLY + +; +;VOID +;EFIAPI +;__aeabi_memcpy ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINT32 Size +; ); +; +__aeabi_memcpy + CMP r2, #0 + BXEQ r14 +loop + LDRB r3, [r1], #1 + STRB r3, [r0], #1 + SUBS r2, r2, #1 + BXEQ r14 + B loop + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy4.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy4.asm new file mode 100644 index 0000000000..fb251c1eaa --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memcpy4.asm @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_memcpy4 + + AREA Memcpy4, CODE, READONLY + +; +;VOID +;EFIAPI +;__aeabi_memcpy ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINT32 Size +; ); +; +__aeabi_memcpy4 + stmdb sp!, {r4, lr} + subs r2, r2, #32 ; 0x20 + bcc memcpy4_label2 +memcpy4_label1 + ldmcsia r1!, {r3, r4, ip, lr} + stmcsia r0!, {r3, r4, ip, lr} + ldmcsia r1!, {r3, r4, ip, lr} + stmcsia r0!, {r3, r4, ip, lr} + subcss r2, r2, #32 ; 0x20 + bcs memcpy4_label1 +memcpy4_label2 + movs ip, r2, lsl #28 + ldmcsia r1!, {r3, r4, ip, lr} + stmcsia r0!, {r3, r4, ip, lr} + ldmmiia r1!, {r3, r4} + stmmiia r0!, {r3, r4} + ldmia sp!, {r4, lr} + movs ip, r2, lsl #30 + ldrcs r3, [r1], #4 + strcs r3, [r0], #4 + bxeq lr + +_memcpy4_lastbytes_aligned + movs r2, r2, lsl #31 + ldrcsh r3, [r1], #2 + ldrmib r2, [r1], #1 + strcsh r3, [r0], #2 + strmib r2, [r0], #1 + bx lr + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S new file mode 100644 index 0000000000..f88464483b --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/memset.S @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------------ +# +# 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 _memset +_memset: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r7, lr} + mov ip, #0 + add r7, sp, #0 + mov lr, r0 + b L9 +L10: + and r3, r1, #255 + add ip, ip, #1 + strb r3, [lr], #1 +L9: + cmp ip, r2 + bne L10 + ldmfd sp!, {r7, pc} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S new file mode 100644 index 0000000000..7af8d21683 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.S @@ -0,0 +1,47 @@ +#------------------------------------------------------------------------------ +# +# 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 ___moddi3 +___moddi3: + @ args = 0, pretend = 0, frame = 8 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r7, lr} + mov r4, r1, asr #31 + add r7, sp, #8 + stmfd sp!, {r10, r11} + mov r10, r3, asr #31 + sub sp, sp, #16 + mov r5, r4 + mov r11, r10 + eor r0, r0, r4 + eor r1, r1, r4 + eor r2, r2, r10 + eor r3, r3, r10 + add ip, sp, #8 + subs r0, r0, r4 + sbc r1, r1, r5 + subs r2, r2, r10 + sbc r3, r3, r11 + str ip, [sp, #0] + bl ___udivmoddi4 + ldrd r0, [sp, #8] + eor r0, r0, r4 + eor r1, r1, r4 + subs r0, r0, r4 + sbc r1, r1, r5 + sub sp, r7, #16 + ldmfd sp!, {r10, r11} + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.c new file mode 100644 index 0000000000..796b179dd3 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/moddi3.c @@ -0,0 +1,77 @@ +/** @file + Compiler intrinsic for 64-bit mod, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT64 __udivmoddi4(UINT64 a, UINT64 b, UINT64* rem); + +// Returns: a % b + +INT64 +__moddi3(INT64 a, INT64 b) +{ + const int bits_in_dword_m1 = (int)(sizeof(INT64) * CHAR_BIT) - 1; + INT64 s = b >> bits_in_dword_m1; // s = b < 0 ? -1 : 0 + b = (b ^ s) - s; // negate if s == -1 + s = a >> bits_in_dword_m1; // s = a < 0 ? -1 : 0 + a = (a ^ s) - s; // negate if s == -1 + INT64 r; + __udivmoddi4(a, b, (UINT64*)&r); + return (r ^ s) - s; // negate if s == -1 +} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S new file mode 100644 index 0000000000..14d8542198 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.S @@ -0,0 +1,28 @@ +#------------------------------------------------------------------------------ +# +# 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 ___modsi3 +___modsi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r7, lr} + add r7, sp, #8 + mov r5, r0 + mov r4, r1 + bl ___divsi3 + mul r0, r4, r0 + rsb r0, r0, r5 + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.c new file mode 100644 index 0000000000..45e0afd0d1 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/modsi3.c @@ -0,0 +1,70 @@ +/** @file + Compiler intrinsic for 32-bit mod, ported from LLVM code. + + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +// Returns: a % b + +INT32 +__modsi3(INT32 a, INT32 b) +{ + return a - (a / b) * b; +} + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S new file mode 100644 index 0000000000..a36dbff8c3 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.S @@ -0,0 +1,59 @@ +#------------------------------------------------------------------------------ +# +# 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 ___muldi3 +___muldi3: + @ args = 0, pretend = 0, frame = 8 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r6, r7, lr} + add r7, sp, #12 + stmfd sp!, {r8, r10, r11} + ldr r11, L4 + mov r4, r0, lsr #16 + and r8, r0, r11 + and ip, r2, r11 + mul lr, ip, r8 + mul ip, r4, ip + sub sp, sp, #8 + add r10, ip, lr, lsr #16 + and ip, r10, r11 + and lr, lr, r11 + mov r6, r2, lsr #16 + str r4, [sp, #4] + add r4, lr, ip, asl #16 + mul ip, r8, r6 + mov r5, r10, lsr #16 + add r10, ip, r4, lsr #16 + and ip, r10, r11 + and lr, r4, r11 + add r4, lr, ip, asl #16 + mul r0, r3, r0 + add ip, r5, r10, lsr #16 + ldr r5, [sp, #4] + mla r0, r2, r1, r0 + mla r5, r6, r5, ip + mov r10, r4 + add r11, r0, r5 + mov r1, r11 + mov r0, r4 + sub sp, r7, #24 + ldmfd sp!, {r8, r10, r11} + ldmfd sp!, {r4, r5, r6, r7, pc} + .p2align 2 +L5: + .align 2 +L4: + .long 65535 diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.c new file mode 100644 index 0000000000..88c88cec2d --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/muldi3.c @@ -0,0 +1,98 @@ +/** @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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + +#include <Base.h> +#include "Llvm_int_lib.h" + + +// Returns: a * b + +static +INT64 +__muldsi3(UINT32 a, UINT32 b) +{ + dwords r; + const int bits_in_word_2 = (int)(sizeof(INT32) * CHAR_BIT) / 2; + const UINT32 lower_mask = (UINT32)~0 >> bits_in_word_2; + r.low = (a & lower_mask) * (b & lower_mask); + UINT32 t = r.low >> bits_in_word_2; + r.low &= lower_mask; + t += (a >> bits_in_word_2) * (b & lower_mask); + r.low += (t & lower_mask) << bits_in_word_2; + r.high = t >> bits_in_word_2; + t = r.low >> bits_in_word_2; + r.low &= lower_mask; + t += (b >> bits_in_word_2) * (a & lower_mask); + r.low += (t & lower_mask) << bits_in_word_2; + r.high += t >> bits_in_word_2; + r.high += (a >> bits_in_word_2) * (b >> bits_in_word_2); + return r.all; +} + +// Returns: a * b + +INT64 +__muldi3(INT64 a, INT64 b) +{ + dwords x; + x.all = a; + dwords y; + y.all = b; + dwords r; + r.all = __muldsi3(x.low, y.low); + r.high += x.high * y.low + x.low * y.high; + return r.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.asm new file mode 100644 index 0000000000..baf7caa006 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/mullu.asm @@ -0,0 +1,49 @@ +//------------------------------------------------------------------------------ +// +// 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 __ARM_ll_mullu + EXPORT __aeabi_lmul + + AREA Math, CODE, READONLY + +; +;INT64 +;EFIAPI +;__aeabi_lmul ( +; IN INT64 Multiplicand +; IN INT32 Multiplier +; ); +; +__ARM_ll_mullu + mov r3, #0 +// Make upper part of INT64 Multiplier 0 and use __aeabi_lmul + +; +;INT64 +;EFIAPI +;__aeabi_lmul ( +; IN INT64 Multiplicand +; IN INT64 Multiplier +; ); +; +__aeabi_lmul + stmdb sp!, {lr} + mov lr, r0 + umull r0, ip, r2, lr + mla r1, r2, r1, ip + mla r1, r3, lr, r1 + ldmia sp!, {pc} + + END diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch.asm new file mode 100644 index 0000000000..2e26160363 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch.asm @@ -0,0 +1,29 @@ +///------------------------------------------------------------------------------ +// +// 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 __ARM_switch8 + + AREA ArmSwitch, CODE, READONLY + +__ARM_switch8 + LDRB r12,[lr,#-1] + CMP r3,r12 + LDRBCC r3,[lr,r3] + LDRBCS r3,[lr,r12] + ADD r12,lr,r3,LSL #1 + BX r12 + + END diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S new file mode 100644 index 0000000000..48e2ab74df --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch16.S @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# 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 +# Compiler intrinsic for ARM compiler +# +# 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.; +# +#**/ +# + +.text +.p2align 2 + +.globl ASM_PFX(__switch16) + + +ASM_PFX(__switch16): + ldrh ip, [lr, #-1] + cmp r0, ip + add r0, lr, r0, lsl #1 + ldrccsh r0, [r0, #1] + add ip, lr, ip, lsl #1 + ldrcssh r0, [ip, #1] + add ip, lr, r0, lsl #1 + bx ip + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S new file mode 100644 index 0000000000..5ecffa6fee --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch32.S @@ -0,0 +1,45 @@ +#------------------------------------------------------------------------------ +# +# 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 +# Compiler intrinsic for ARM compiler +# +# 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.; +# +#**/ +# + +.text +.p2align 2 + +.globl ASM_PFX(__switch32) + + +ASM_PFX(__switch32): + ldr ip, [lr, #-1] + cmp r0, ip + add r0, lr, r0, lsl #2 + ldrcc r0, [r0, #3] + add ip, lr, ip, lsl #2 + ldrcs r0, [ip, #3] + add ip, lr, r0 + bx ip + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S new file mode 100644 index 0000000000..947156ee57 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switch8.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# 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 +# Compiler intrinsic for ARM compiler +# +# 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.; +# +#**/ +# + +.text +.p2align 2 + +.globl ASM_PFX(__switch8) + + +ASM_PFX(__switch8): + ldrb ip, [lr, #-1] + cmp r0, ip + ldrccsb r0, [lr, r0] + ldrcssb r0, [lr, ip] + add ip, lr, r0, lsl #1 + bx ip + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S new file mode 100644 index 0000000000..e49204fdd4 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/switchu8.S @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# 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 +# Compiler intrinsic for ARM compiler +# +# 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.; +# +#**/ +# + +.text +.p2align 2 + +.globl ASM_PFX(__switchu8) + + +ASM_PFX(__switchu8): + ldrb ip,[lr,#-1] + cmp r3,ip + ldrccb r3,[lr,r3] + ldrcsb r3,[lr,ip] + add ip,lr,r3,LSL #1 + bx ip + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.c new file mode 100644 index 0000000000..0cf1404b32 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/ucmpdi2.c @@ -0,0 +1,82 @@ +/** @file + Compiler intrinsic for 64-bit compare, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + + +// Returns: if (a < b) returns 0 +// if (a == b) returns 1 +// if (a > b) returns 2 + +UINT32 +__ucmpdi2(UINT64 a, UINT64 b) +{ + udwords x; + x.all = a; + udwords y; + y.all = b; + if (x.high < y.high) + return 0; + if (x.high > y.high) + return 2; + if (x.low < y.low) + return 0; + if (x.low > y.low) + return 2; + return 1; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S new file mode 100644 index 0000000000..fd7715da66 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.S @@ -0,0 +1,28 @@ +#------------------------------------------------------------------------------ +# +# 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 ___udivdi3 +___udivdi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r7, lr} + add r7, sp, #0 + sub sp, sp, #8 + mov ip, #0 + str ip, [sp, #0] + bl ___udivmoddi4 + sub sp, r7, #0 + ldmfd sp!, {r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.c new file mode 100644 index 0000000000..1a04ea7dd1 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivdi3.c @@ -0,0 +1,71 @@ +/** @file + Compiler intrinsic for 64-bit unisigned div, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT64 __udivmoddi4 (UINT64 a, UINT64 b, UINT64 *rem); + +// Returns: a / b + +UINT64 +__udivdi3(UINT64 a, UINT64 b) +{ + return __udivmoddi4(a, b, 0); +} + + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S new file mode 100644 index 0000000000..1e54baec24 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.S @@ -0,0 +1,243 @@ +#------------------------------------------------------------------------------ +# +# 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 ___udivmoddi4 +___udivmoddi4: + @ args = 8, pretend = 0, frame = 16 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r6, r7, lr} + add r7, sp, #12 + stmfd sp!, {r10, r11} + sub sp, sp, #20 + stmia sp, {r2-r3} + ldr r6, [sp, #48] + orrs r2, r2, r3 + mov r10, r0 + mov r11, r1 + beq L2 + subs ip, r1, #0 + bne L4 + cmp r3, #0 + bne L6 + cmp r6, #0 + beq L8 + mov r1, r2 + bl ___umodsi3 + mov r1, #0 + stmia r6, {r0-r1} +L8: + ldr r1, [sp, #0] + mov r0, r10 + b L45 +L6: + cmp r6, #0 + movne r1, #0 + stmneia r6, {r0-r1} + b L2 +L4: + ldr r1, [sp, #0] + cmp r1, #0 + bne L12 + ldr r2, [sp, #4] + cmp r2, #0 + bne L14 + cmp r6, #0 + beq L16 + mov r1, r2 + mov r0, r11 + bl ___umodsi3 + mov r1, #0 + stmia r6, {r0-r1} +L16: + ldr r1, [sp, #4] + mov r0, r11 +L45: + bl ___udivsi3 +L46: + mov r10, r0 + mov r11, #0 + b L10 +L14: + subs r1, r0, #0 + bne L18 + cmp r6, #0 + beq L16 + ldr r1, [sp, #4] + mov r0, r11 + bl ___umodsi3 + mov r4, r10 + mov r5, r0 + stmia r6, {r4-r5} + b L16 +L18: + sub r3, r2, #1 + tst r2, r3 + bne L22 + cmp r6, #0 + movne r4, r0 + andne r5, ip, r3 + stmneia r6, {r4-r5} +L24: + rsb r3, r2, #0 + and r3, r2, r3 + clz r3, r3 + rsb r3, r3, #31 + mov r0, ip, lsr r3 + b L46 +L22: + clz r2, r2 + clz r3, ip + rsb r3, r3, r2 + cmp r3, #30 + bhi L48 + rsb r2, r3, #31 + add lr, r3, #1 + mov r3, r1, asl r2 + str r3, [sp, #12] + mov r3, r1, lsr lr + ldr r0, [sp, #0] + mov r5, ip, lsr lr + orr r4, r3, ip, asl r2 + str r0, [sp, #8] + b L29 +L12: + ldr r3, [sp, #4] + cmp r3, #0 + bne L30 + sub r3, r1, #1 + tst r1, r3 + bne L32 + cmp r6, #0 + andne r3, r3, r0 + movne r2, r3 + movne r3, #0 + stmneia r6, {r2-r3} +L34: + cmp r1, #1 + beq L10 + rsb r3, r1, #0 + and r3, r1, r3 + clz r3, r3 + rsb r0, r3, #31 + mov r1, ip, lsr r0 + rsb r3, r0, #32 + mov r0, r10, lsr r0 + orr ip, r0, ip, asl r3 + str r1, [sp, #12] + str ip, [sp, #8] + ldrd r10, [sp, #8] + b L10 +L32: + clz r2, r1 + clz r3, ip + rsb r3, r3, r2 + rsb r4, r3, #31 + mov r2, r0, asl r4 + mvn r1, r3 + and r2, r2, r1, asr #31 + add lr, r3, #33 + str r2, [sp, #8] + add r2, r3, #1 + mov r3, r3, asr #31 + and r0, r3, r0, asl r1 + mov r3, r10, lsr r2 + orr r3, r3, ip, asl r4 + and r3, r3, r1, asr #31 + orr r0, r0, r3 + mov r3, ip, lsr lr + str r0, [sp, #12] + mov r0, r10, lsr lr + and r5, r3, r2, asr #31 + rsb r3, lr, #31 + mov r3, r3, asr #31 + orr r0, r0, ip, asl r1 + and r3, r3, ip, lsr r2 + and r0, r0, r2, asr #31 + orr r4, r3, r0 + b L29 +L30: + clz r2, r3 + clz r3, ip + rsb r3, r3, r2 + cmp r3, #31 + bls L37 +L48: + cmp r6, #0 + stmneia r6, {r10-r11} + b L2 +L37: + rsb r1, r3, #31 + mov r0, r0, asl r1 + add lr, r3, #1 + mov r2, #0 + str r0, [sp, #12] + mov r0, r10, lsr lr + str r2, [sp, #8] + sub r2, r3, #31 + and r0, r0, r2, asr #31 + mov r3, ip, lsr lr + orr r4, r0, ip, asl r1 + and r5, r3, r2, asr #31 +L29: + mov ip, #0 + mov r10, ip + b L40 +L41: + ldr r1, [sp, #12] + ldr r2, [sp, #8] + mov r3, r4, lsr #31 + orr r5, r3, r5, asl #1 + mov r3, r1, lsr #31 + orr r4, r3, r4, asl #1 + mov r3, r2, lsr #31 + orr r0, r3, r1, asl #1 + orr r1, ip, r2, asl #1 + ldmia sp, {r2-r3} + str r0, [sp, #12] + subs r2, r2, r4 + sbc r3, r3, r5 + str r1, [sp, #8] + subs r0, r2, #1 + sbc r1, r3, #0 + mov r2, r1, asr #31 + ldmia sp, {r0-r1} + mov r3, r2 + and ip, r2, #1 + and r3, r3, r1 + and r2, r2, r0 + subs r4, r4, r2 + sbc r5, r5, r3 + add r10, r10, #1 +L40: + cmp r10, lr + bne L41 + ldrd r0, [sp, #8] + adds r0, r0, r0 + adc r1, r1, r1 + cmp r6, #0 + orr r10, r0, ip + mov r11, r1 + stmneia r6, {r4-r5} + b L10 +L2: + mov r10, #0 + mov r11, #0 +L10: + mov r0, r10 + mov r1, r11 + sub sp, r7, #20 + ldmfd sp!, {r10, r11} + ldmfd sp!, {r4, r5, r6, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.c new file mode 100644 index 0000000000..58f7554cc3 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivmoddi4.c @@ -0,0 +1,287 @@ +/** @file + Compiler intrinsic for 64-bit compare, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +// Effects: if rem != 0, *rem = a % b +// Returns: a / b + +// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide + +UINT64 +__udivmoddi4 (UINT64 a, UINT64 b, UINT64* rem) +{ + const unsigned n_uword_bits = sizeof(UINT32) * CHAR_BIT; + const unsigned n_udword_bits = sizeof(UINT64) * CHAR_BIT; + udwords n; + n.all = a; + udwords d; + d.all = b; + udwords q; + udwords r; + unsigned sr; + + if (b == 0) { +// ASSERT (FALSE); + return 0; + } + + // special cases, X is unknown, K != 0 + if (n.high == 0) + { + if (d.high == 0) + { + // 0 X + // --- + // 0 X + if (rem) + *rem = n.low % d.low; + return n.low / d.low; + } + // 0 X + // --- + // K X + if (rem) + *rem = n.low; + return 0; + } + // n.high != 0 + if (d.low == 0) + { + if (d.high == 0) + { + // K X + // --- + // 0 0 + if (rem) + *rem = n.high % d.low; + return n.high / d.low; + } + // d.high != 0 + if (n.low == 0) + { + // K 0 + // --- + // K 0 + if (rem) + { + r.high = n.high % d.high; + r.low = 0; + *rem = r.all; + } + return n.high / d.high; + } + // K K + // --- + // K 0 + if ((d.high & (d.high - 1)) == 0) // if d is a power of 2 + { + if (rem) + { + r.low = n.low; + r.high = n.high & (d.high - 1); + *rem = r.all; + } + return n.high >> COUNT_TRAILING_ZEROS(d.high); + } + // K K + // --- + // K 0 + sr = COUNT_LEADING_ZEROS(d.high) - COUNT_LEADING_ZEROS(n.high); + // 0 <= sr <= n_uword_bits - 2 or sr large + if (sr > n_uword_bits - 2) + { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + // 1 <= sr <= n_uword_bits - 1 + // q.all = n.all << (n_udword_bits - sr); + q.low = 0; + q.high = n.low << (n_uword_bits - sr); + // r.all = n.all >> sr; + r.high = n.high >> sr; + r.low = (n.high << (n_uword_bits - sr)) | (n.low >> sr); + } + else // d.low != 0 + { + if (d.high == 0) + { + // K X + // --- + // 0 K + if ((d.low & (d.low - 1)) == 0) // if d is a power of 2 + { + if (rem) + *rem = n.low & (d.low - 1); + if (d.low == 1) + return n.all; + unsigned sr = COUNT_TRAILING_ZEROS(d.low); + q.high = n.high >> sr; + q.low = (n.high << (n_uword_bits - sr)) | (n.low >> sr); + return q.all; + } + // K X + // --- + // 0 K + sr = 1 + n_uword_bits + COUNT_LEADING_ZEROS(d.low) - COUNT_LEADING_ZEROS(n.high); + // 2 <= sr <= n_udword_bits - 1 + // q.all = n.all << (n_udword_bits - sr); + // r.all = n.all >> sr; + // if (sr == n_uword_bits) + // { + // q.low = 0; + // q.high = n.low; + // r.high = 0; + // r.low = n.high; + // } + // else if (sr < n_uword_bits) // 2 <= sr <= n_uword_bits - 1 + // { + // q.low = 0; + // q.high = n.low << (n_uword_bits - sr); + // r.high = n.high >> sr; + // r.low = (n.high << (n_uword_bits - sr)) | (n.low >> sr); + // } + // else // n_uword_bits + 1 <= sr <= n_udword_bits - 1 + // { + // q.low = n.low << (n_udword_bits - sr); + // q.high = (n.high << (n_udword_bits - sr)) | + // (n.low >> (sr - n_uword_bits)); + // r.high = 0; + // r.low = n.high >> (sr - n_uword_bits); + // } + q.low = (n.low << (n_udword_bits - sr)) & + ((INT32)(n_uword_bits - sr) >> (n_uword_bits-1)); + q.high = ((n.low << ( n_uword_bits - sr)) & + ((INT32)(sr - n_uword_bits - 1) >> (n_uword_bits-1))) | + (((n.high << (n_udword_bits - sr)) | + (n.low >> (sr - n_uword_bits))) & + ((INT32)(n_uword_bits - sr) >> (n_uword_bits-1))); + r.high = (n.high >> sr) & + ((INT32)(sr - n_uword_bits) >> (n_uword_bits-1)); + r.low = ((n.high >> (sr - n_uword_bits)) & + ((INT32)(n_uword_bits - sr - 1) >> (n_uword_bits-1))) | + (((n.high << (n_uword_bits - sr)) | + (n.low >> sr)) & + ((INT32)(sr - n_uword_bits) >> (n_uword_bits-1))); + } + else + { + // K X + // --- + // K K + sr = COUNT_LEADING_ZEROS(d.high) - COUNT_LEADING_ZEROS(n.high); + // 0 <= sr <= n_uword_bits - 1 or sr large + if (sr > n_uword_bits - 1) + { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + // 1 <= sr <= n_uword_bits + // q.all = n.all << (n_udword_bits - sr); + q.low = 0; + q.high = n.low << (n_uword_bits - sr); + // r.all = n.all >> sr; + // if (sr < n_uword_bits) + // { + // r.high = n.high >> sr; + // r.low = (n.high << (n_uword_bits - sr)) | (n.low >> sr); + // } + // else + // { + // r.high = 0; + // r.low = n.high; + // } + r.high = (n.high >> sr) & + ((INT32)(sr - n_uword_bits) >> (n_uword_bits-1)); + r.low = (n.high << (n_uword_bits - sr)) | + ((n.low >> sr) & + ((INT32)(sr - n_uword_bits) >> (n_uword_bits-1))); + } + } + // Not a special case + // q and r are initialized with: + // q.all = n.all << (n_udword_bits - sr); + // r.all = n.all >> sr; + // 1 <= sr <= n_udword_bits - 1 + UINT32 carry = 0; + for (; sr > 0; --sr) + { + // r:q = ((r:q) << 1) | carry + r.high = (r.high << 1) | (r.low >> (n_uword_bits - 1)); + r.low = (r.low << 1) | (q.high >> (n_uword_bits - 1)); + q.high = (q.high << 1) | (q.low >> (n_uword_bits - 1)); + q.low = (q.low << 1) | carry; + // carry = 0; + // if (r.all >= d.all) + // { + // r.all -= d.all; + // carry = 1; + // } + const INT64 s = (INT64)(d.all - r.all - 1) >> (n_udword_bits - 1); + carry = s & 1; + r.all -= d.all & s; + } + q.all = (q.all << 1) | carry; + if (rem) + *rem = r.all; + return q.all; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S new file mode 100644 index 0000000000..e5a0afa053 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.S @@ -0,0 +1,57 @@ +#------------------------------------------------------------------------------ +# +# 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 ___udivsi3 +___udivsi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + cmp r1, #0 + cmpne r0, #0 + stmfd sp!, {r4, r5, r7, lr} + add r7, sp, #8 + beq L2 + clz r2, r1 + clz r3, r0 + rsb r3, r3, r2 + cmp r3, #31 + bhi L2 + ldmeqfd sp!, {r4, r5, r7, pc} + add r5, r3, #1 + rsb r3, r3, #31 + mov lr, #0 + mov r2, r0, asl r3 + mov ip, r0, lsr r5 + mov r4, lr + b L8 +L9: + mov r0, r2, lsr #31 + orr ip, r0, ip, asl #1 + orr r2, r3, lr + rsb r3, ip, r1 + sub r3, r3, #1 + and r0, r1, r3, asr #31 + mov lr, r3, lsr #31 + rsb ip, r0, ip + add r4, r4, #1 +L8: + cmp r4, r5 + mov r3, r2, asl #1 + bne L9 + orr r0, r3, lr + ldmfd sp!, {r4, r5, r7, pc} +L2: + mov r0, #0 + ldmfd sp!, {r4, r5, r7, pc} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.c new file mode 100644 index 0000000000..59d5b23643 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/udivsi3.c @@ -0,0 +1,111 @@ +/** @file + Compiler intrinsic for 32-bit unsigned div, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + + +// Returns: n / d + +// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide + +UINT32 +__udivsi3(UINT32 n, UINT32 d) +{ + const unsigned n_uword_bits = sizeof(UINT32) * CHAR_BIT; + UINT32 q; + UINT32 r; + unsigned sr; + + // special cases + if (d == 0) { +// ASSERT (FALSE); + return 0; // ?! + } + if (n == 0) + return 0; + + sr = COUNT_LEADING_ZEROS(d) - COUNT_LEADING_ZEROS(n); + // 0 <= sr <= n_uword_bits - 1 or sr large + if (sr > n_uword_bits - 1) // d > r + return 0; + if (sr == n_uword_bits - 1) // d == 1 + return n; + ++sr; + // 1 <= sr <= n_uword_bits - 1 + // Not a special case + q = n << (n_uword_bits - sr); + r = n >> sr; + UINT32 carry = 0; + for (; sr > 0; --sr) + { + // r:q = ((r:q) << 1) | carry + r = (r << 1) | (q >> (n_uword_bits - 1)); + q = (q << 1) | carry; + // carry = 0; + // if (r.all >= d.all) + // { + // r.all -= d.all; + // carry = 1; + // } + const INT32 s = (INT32)(d - r - 1) >> (n_uword_bits - 1); + carry = s & 1; + r -= d & s; + } + q = (q << 1) | carry; + return q; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.asm new file mode 100644 index 0000000000..a26ac762a4 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uldiv.asm @@ -0,0 +1,268 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_uldivmod + + AREA Uldivmod, CODE, READONLY + +; +;UINT64 +;EFIAPI +;__aeabi_uldivmod ( +; IN UINT64 Dividend +; IN UINT64 Divisor +; ) +; +__aeabi_uldivmod + stmdb sp!, {r4, r5, r6, lr} + mov r4, r1 + mov r5, r0 + mov r6, #0 ; 0x0 + orrs ip, r3, r2, lsr #31 + bne __aeabi_uldivmod_label1 + tst r2, r2 + beq _ll_div0 + movs ip, r2, lsr #15 + addeq r6, r6, #16 ; 0x10 + mov ip, r2, lsl r6 + movs lr, ip, lsr #23 + moveq ip, ip, lsl #8 + addeq r6, r6, #8 ; 0x8 + movs lr, ip, lsr #27 + moveq ip, ip, lsl #4 + addeq r6, r6, #4 ; 0x4 + movs lr, ip, lsr #29 + moveq ip, ip, lsl #2 + addeq r6, r6, #2 ; 0x2 + movs lr, ip, lsr #30 + moveq ip, ip, lsl #1 + addeq r6, r6, #1 ; 0x1 + b _ll_udiv_small +__aeabi_uldivmod_label1 + tst r3, #-2147483648 ; 0x80000000 + bne __aeabi_uldivmod_label2 + movs ip, r3, lsr #15 + addeq r6, r6, #16 ; 0x10 + mov ip, r3, lsl r6 + movs lr, ip, lsr #23 + moveq ip, ip, lsl #8 + addeq r6, r6, #8 ; 0x8 + movs lr, ip, lsr #27 + moveq ip, ip, lsl #4 + addeq r6, r6, #4 ; 0x4 + movs lr, ip, lsr #29 + moveq ip, ip, lsl #2 + addeq r6, r6, #2 ; 0x2 + movs lr, ip, lsr #30 + addeq r6, r6, #1 ; 0x1 + rsb r3, r6, #32 ; 0x20 + moveq ip, ip, lsl #1 + orr ip, ip, r2, lsr r3 + mov lr, r2, lsl r6 + b _ll_udiv_big +__aeabi_uldivmod_label2 + mov ip, r3 + mov lr, r2 + b _ll_udiv_ginormous + +_ll_udiv_small + cmp r4, ip, lsl #1 + mov r3, #0 ; 0x0 + subcs r4, r4, ip, lsl #1 + addcs r3, r3, #2 ; 0x2 + cmp r4, ip + subcs r4, r4, ip + adcs r3, r3, #0 ; 0x0 + add r2, r6, #32 ; 0x20 + cmp r2, #32 ; 0x20 + rsb ip, ip, #0 ; 0x0 + bcc _ll_udiv_small_label1 + orrs r0, r4, r5, lsr #30 + moveq r4, r5 + moveq r5, #0 ; 0x0 + subeq r2, r2, #32 ; 0x20 +_ll_udiv_small_label1 + mov r1, #0 ; 0x0 + cmp r2, #16 ; 0x10 + bcc _ll_udiv_small_label2 + movs r0, r4, lsr #14 + moveq r4, r4, lsl #16 + addeq r1, r1, #16 ; 0x10 +_ll_udiv_small_label2 + sub lr, r2, r1 + cmp lr, #8 ; 0x8 + bcc _ll_udiv_small_label3 + movs r0, r4, lsr #22 + moveq r4, r4, lsl #8 + addeq r1, r1, #8 ; 0x8 +_ll_udiv_small_label3 + rsb r0, r1, #32 ; 0x20 + sub r2, r2, r1 + orr r4, r4, r5, lsr r0 + mov r5, r5, lsl r1 + cmp r2, #1 ; 0x1 + bcc _ll_udiv_small_label5 + sub r2, r2, #1 ; 0x1 + and r0, r2, #7 ; 0x7 + eor r0, r0, #7 ; 0x7 + adds r0, r0, r0, lsl #1 + add pc, pc, r0, lsl #2 + nop ; (mov r0,r0) +_ll_udiv_small_label4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + rsbcc r4, ip, r4 + adcs r5, r5, r5 + adcs r4, ip, r4, lsl #1 + sub r2, r2, #8 ; 0x8 + tst r2, r2 + rsbcc r4, ip, r4 + bpl _ll_udiv_small_label4 +_ll_udiv_small_label5 + mov r2, r4, lsr r6 + bic r4, r4, r2, lsl r6 + adcs r0, r5, r5 + adc r1, r4, r4 + add r1, r1, r3, lsl r6 + mov r3, #0 ; 0x0 + ldmia sp!, {r4, r5, r6, pc} + +_ll_udiv_big + subs r0, r5, lr + mov r3, #0 ; 0x0 + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 ; 0x0 + subs r0, r5, lr + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 ; 0x0 + subs r0, r5, lr + sbcs r1, r4, ip + movcs r5, r0 + movcs r4, r1 + adcs r3, r3, #0 ; 0x0 + mov r1, #0 ; 0x0 + rsbs lr, lr, #0 ; 0x0 + rsc ip, ip, #0 ; 0x0 + cmp r6, #16 ; 0x10 + bcc _ll_udiv_big_label1 + movs r0, r4, lsr #14 + moveq r4, r4, lsl #16 + addeq r1, r1, #16 ; 0x10 +_ll_udiv_big_label1 + sub r2, r6, r1 + cmp r2, #8 ; 0x8 + bcc _ll_udiv_big_label2 + movs r0, r4, lsr #22 + moveq r4, r4, lsl #8 + addeq r1, r1, #8 ; 0x8 +_ll_udiv_big_label2 + rsb r0, r1, #32 ; 0x20 + sub r2, r6, r1 + orr r4, r4, r5, lsr r0 + mov r5, r5, lsl r1 + cmp r2, #1 ; 0x1 + bcc _ll_udiv_big_label4 + sub r2, r2, #1 ; 0x1 + and r0, r2, #3 ; 0x3 + rsb r0, r0, #3 ; 0x3 + adds r0, r0, r0, lsl #1 + add pc, pc, r0, lsl #3 + nop ; (mov r0,r0) +_ll_udiv_big_label3 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + movcs r5, r0 + movcs r4, r1 + sub r2, r2, #4 ; 0x4 + adcs r5, r5, r5 + adcs r4, r4, r4 + adcs r0, lr, r5 + adcs r1, ip, r4 + tst r2, r2 + movcs r5, r0 + movcs r4, r1 + bpl _ll_udiv_big_label3 +_ll_udiv_big_label4 + mov r1, #0 ; 0x0 + mov r2, r5, lsr r6 + bic r5, r5, r2, lsl r6 + adcs r0, r5, r5 + adc r1, r1, #0 ; 0x0 + movs lr, r3, lsl r6 + mov r3, r4, lsr r6 + bic r4, r4, r3, lsl r6 + adc r1, r1, #0 ; 0x0 + adds r0, r0, lr + orr r2, r2, r4, ror r6 + adc r1, r1, #0 ; 0x0 + ldmia sp!, {r4, r5, r6, pc} + +_ll_udiv_ginormous + subs r2, r5, lr + mov r1, #0 ; 0x0 + sbcs r3, r4, ip + adc r0, r1, r1 + movcc r2, r5 + movcc r3, r4 + ldmia sp!, {r4, r5, r6, pc} + +_ll_div0 + ldmia sp!, {r4, r5, r6, lr} + mov r0, #0 ; 0x0 + mov r1, #0 ; 0x0 + b __aeabi_ldiv0 + +__aeabi_ldiv0 + BX r14 + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S new file mode 100644 index 0000000000..6396036c04 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.S @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------------ +# +# 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 ___umoddi3 +___umoddi3: + @ args = 0, pretend = 0, frame = 8 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r7, lr} + add r7, sp, #0 + sub sp, sp, #16 + add ip, sp, #8 + str ip, [sp, #0] + bl ___udivmoddi4 + ldrd r0, [sp, #8] + sub sp, r7, #0 + ldmfd sp!, {r7, pc} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.c new file mode 100644 index 0000000000..73d796e499 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umoddi3.c @@ -0,0 +1,72 @@ +/** @file + Compiler intrinsic for 64-bit unsigned mod, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + +UINT64 __udivmoddi4(UINT64 a, UINT64 b, UINT64* rem); + +// Returns: a % b + +UINT64 +__umoddi3(UINT64 a, UINT64 b) +{ + UINT64 r; + __udivmoddi4(a, b, &r); + return r; +} + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S new file mode 100644 index 0000000000..4cde76beb5 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.S @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------------ +# +# 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 ___umodsi3 +___umodsi3: + @ args = 0, pretend = 0, frame = 0 + @ frame_needed = 1, uses_anonymous_args = 0 + stmfd sp!, {r4, r5, r7, lr} + add r7, sp, #8 + mov r5, r0 + mov r4, r1 + bl L___udivsi3$stub + mul r0, r4, r0 + rsb r0, r0, r5 + ldmfd sp!, {r4, r5, r7, pc} + .section __TEXT,__symbol_stub4,symbol_stubs,none,12 + .align 2 +L___udivsi3$stub: + .indirect_symbol ___udivsi3 + ldr ip, L___udivsi3$slp + ldr pc, [ip, #0] +L___udivsi3$slp: + .long L___udivsi3$lazy_ptr + .lazy_symbol_pointer +L___udivsi3$lazy_ptr: + .indirect_symbol ___udivsi3 + .long dyld_stub_binding_helper diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.c b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.c new file mode 100644 index 0000000000..09d4008e78 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/umodsi3.c @@ -0,0 +1,68 @@ +/** @file + Compiler intrinsic for 32-bit unsigned mod, ported from LLVM code. + + 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. + +**/ +/** + University of Illinois/NCSA + Open Source License + + Copyright (c) 2003-2008 University of Illinois at Urbana-Champaign. + All rights reserved. + + Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal with + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +**/ + + +#include "Llvm_int_lib.h" + + +// Returns: a % b + +UINT32 +__umodsi3(UINT32 a, UINT32 b) +{ + return a - (a / b) * b; +} diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uread.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uread.asm new file mode 100644 index 0000000000..1d3d192821 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uread.asm @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_uread4 + + AREA Uread4, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_uread4 ( +; IN VOID *Pointer +; ); +; +__aeabi_uread4 + ldrb r2, [r0, #1] + ldrb r1, [r0] + ldrb r3, [r0, #2] + ldrb r0, [r0, #3] + orr r1, r1, r2, lsl #8 + orr r1, r1, r3, lsl #16 + orr r0, r1, r0, lsl #24 + bx lr + + END diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uwrite.asm b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uwrite.asm new file mode 100644 index 0000000000..d6a1e2fb00 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/Arm/uwrite.asm @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +// +// 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 __aeabi_uwrite4 + + AREA Uwrite4, CODE, READONLY + +; +;UINT32 +;EFIAPI +;__aeabi_uwrite4 ( +; IN UINT32 Data, +; IN VOID *Pointer +; ); +; +; +__aeabi_uwrite4 + mov r2, r0, lsr #8 + strb r0, [r1] + strb r2, [r1, #1] + mov r2, r0, lsr #16 + strb r2, [r1, #2] + mov r2, r0, lsr #24 + strb r2, [r1, #3] + bx lr + + END + diff --git a/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf b/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf new file mode 100644 index 0000000000..b1429737c7 --- /dev/null +++ b/ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf @@ -0,0 +1,92 @@ +#%HEADER% +#/** @file +# Base Library implementation. +# +# Copyright (c) 2009, Apple, Inc. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = CompilerIntrinsicsLib + FILE_GUID = 855274FA-3575-4C20-9709-C031DC5589FA + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CompilerIntrinsicsLib + + +[Sources.common] + + +[Sources.ARM] + Arm/mullu.asm | RVCT + Arm/switch.asm | RVCT + Arm/llsr.asm | RVCT + Arm/memcpy.asm | RVCT + Arm/memcpy4.asm | RVCT + Arm/uread.asm | RVCT + Arm/uwrite.asm | RVCT + Arm/lasr.asm | RVCT + Arm/llsl.asm | RVCT + Arm/div.asm | RVCT + Arm/uldiv.asm | RVCT + Arm/ldivmod.asm | RVCT + + +# +# Move .c to .s to work around LLVM issues +# +# Arm/ashrdi3.c | GCC +# Arm/ashldi3.c | GCC +# Arm/divdi3.c | GCC +# Arm/divsi3.c | GCC +# Arm/lshrdi3.c | GCC + Arm/ashrdi3.S | GCC + Arm/ashldi3.S | GCC + Arm/divdi3.S | GCC + Arm/divsi3.S | GCC + Arm/lshrdi3.S | GCC + + Arm/memcpy.S | GCC + Arm/memset.S | GCC + +# Arm/modsi3.c | GCC +# Arm/moddi3.c | GCC +# Arm/muldi3.c | GCC + Arm/modsi3.S | GCC + Arm/moddi3.S | GCC + Arm/muldi3.S | GCC + +# Arm/udivsi3.c | GCC +# Arm/umodsi3.c | GCC +# Arm/udivdi3.c | GCC +# Arm/umoddi3.c | GCC +# Arm/udivmoddi4.c | GCC + Arm/udivsi3.S | GCC + Arm/umodsi3.S | GCC + Arm/udivdi3.S | GCC + Arm/umoddi3.S | GCC + Arm/udivmoddi4.S | GCC + +# Arm/clzsi2.c | GCC +# Arm/ctzsi2.c | GCC +# Arm/ucmpdi2.c | GCC + Arm/switch8.S | GCC + Arm/switchu8.S | GCC + Arm/switch16.S | GCC + Arm/switch32.S | GCC + + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + diff --git a/ArmPkg/Library/SemiHostingDebugLib/DebugLib.c b/ArmPkg/Library/SemiHostingDebugLib/DebugLib.c new file mode 100644 index 0000000000..61e3aac3c2 --- /dev/null +++ b/ArmPkg/Library/SemiHostingDebugLib/DebugLib.c @@ -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);
+}
diff --git a/ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf b/ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf new file mode 100644 index 0000000000..683f03f2f3 --- /dev/null +++ b/ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf @@ -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
+
diff --git a/ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf b/ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf new file mode 100644 index 0000000000..c0a540342a --- /dev/null +++ b/ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf @@ -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
diff --git a/ArmPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c b/ArmPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c new file mode 100644 index 0000000000..df43f31413 --- /dev/null +++ b/ArmPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c @@ -0,0 +1,144 @@ +/** @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 ();
+}
+
diff --git a/ArmPkg/Library/SemihostLib/Arm/SemihostLib.c b/ArmPkg/Library/SemihostLib/Arm/SemihostLib.c new file mode 100644 index 0000000000..e1a515ef21 --- /dev/null +++ b/ArmPkg/Library/SemihostLib/Arm/SemihostLib.c @@ -0,0 +1,221 @@ +/** @file + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +#include <Uefi.h> + +#include <Library/BaseLib.h> +#include <Library/SemihostLib.h> + +#include "SemihostPrivate.h" + +BOOLEAN +SemihostConnectionSupported ( + VOID + ) +{ + return SEMIHOST_SUPPORTED; +} + +EFI_STATUS +SemihostFileOpen ( + IN CHAR8 *FileName, + IN UINT32 Mode, + OUT UINT32 *FileHandle + ) +{ + SEMIHOST_FILE_OPEN_BLOCK OpenBlock; + INT32 Result; + + if (FileHandle == NULL) + return EFI_INVALID_PARAMETER; + + OpenBlock.FileName = FileName; + OpenBlock.Mode = Mode; + OpenBlock.NameLength = AsciiStrLen(FileName); + + Result = Semihost_SYS_OPEN(&OpenBlock); + + if (Result == -1) + { + return EFI_NOT_FOUND; + } + else + { + *FileHandle = Result; + return EFI_SUCCESS; + } +} + +EFI_STATUS +SemihostFileSeek ( + IN UINT32 FileHandle, + IN UINT32 Offset + ) +{ + SEMIHOST_FILE_SEEK_BLOCK SeekBlock; + INT32 Result; + + SeekBlock.Handle = FileHandle; + SeekBlock.Location = Offset; + + Result = Semihost_SYS_SEEK(&SeekBlock); + + if (Result == 0) + return EFI_SUCCESS; + else + return EFI_ABORTED; +} + +EFI_STATUS +SemihostFileRead ( + IN UINT32 FileHandle, + IN OUT UINT32 *Length, + OUT VOID *Buffer + ) +{ + SEMIHOST_FILE_READ_WRITE_BLOCK ReadBlock; + UINT32 Result; + + if ((Length == NULL) || (Buffer == NULL)) + return EFI_INVALID_PARAMETER; + + ReadBlock.Handle = FileHandle; + ReadBlock.Buffer = Buffer; + ReadBlock.Length = *Length; + + Result = Semihost_SYS_READ(&ReadBlock); + + if (Result == *Length) + { + return EFI_ABORTED; + } + else + { + *Length -= Result; + return EFI_SUCCESS; + } +} + +EFI_STATUS +SemihostFileWrite ( + IN UINT32 FileHandle, + IN OUT UINT32 *Length, + IN VOID *Buffer + ) +{ + SEMIHOST_FILE_READ_WRITE_BLOCK WriteBlock; + + if ((Length == NULL) || (Buffer == NULL)) + return EFI_INVALID_PARAMETER; + + WriteBlock.Handle = FileHandle; + WriteBlock.Buffer = Buffer; + WriteBlock.Length = *Length; + + *Length = Semihost_SYS_WRITE(&WriteBlock); + + return EFI_SUCCESS; +} + +EFI_STATUS +SemihostFileClose ( + IN UINT32 FileHandle + ) +{ + INT32 Result = Semihost_SYS_CLOSE(&FileHandle); + + if (Result == -1) + return EFI_INVALID_PARAMETER; + else + return EFI_SUCCESS; +} + +EFI_STATUS +SemihostFileLength ( + IN UINT32 FileHandle, + OUT UINT32 *Length + ) +{ + INT32 Result; + + if (Length == NULL) + return EFI_INVALID_PARAMETER; + + Result = Semihost_SYS_FLEN(&FileHandle); + + if (Result == -1) + { + return EFI_ABORTED; + } + else + { + *Length = Result; + return EFI_SUCCESS; + } +} + +EFI_STATUS +SemihostFileRemove ( + IN CHAR8 *FileName + ) +{ + SEMIHOST_FILE_REMOVE_BLOCK RemoveBlock; + UINT32 Result; + + RemoveBlock.FileName = FileName; + RemoveBlock.NameLength = AsciiStrLen(FileName); + + Result = Semihost_SYS_REMOVE(&RemoveBlock); + + if (Result == 0) + return EFI_SUCCESS; + else + return EFI_ABORTED; +} + +CHAR8 +SemihostReadCharacter ( + VOID + ) +{ + return Semihost_SYS_READC(); +} + +VOID +SemihostWriteCharacter ( + IN CHAR8 Character + ) +{ + Semihost_SYS_WRITEC(&Character); +} + +VOID +SemihostWriteString ( + IN CHAR8 *String + ) +{ + Semihost_SYS_WRITE0(String); +} + +UINT32 +SemihostSystem ( + IN CHAR8 *CommandLine + ) +{ + SEMIHOST_SYSTEM_BLOCK SystemBlock; + + SystemBlock.CommandLine = CommandLine; + SystemBlock.CommandLength = AsciiStrLen(CommandLine); + + return Semihost_SYS_SYSTEM(&SystemBlock); +} diff --git a/ArmPkg/Library/SemihostLib/Arm/SemihostPrivate.h b/ArmPkg/Library/SemihostLib/Arm/SemihostPrivate.h new file mode 100644 index 0000000000..e82111430a --- /dev/null +++ b/ArmPkg/Library/SemihostLib/Arm/SemihostPrivate.h @@ -0,0 +1,162 @@ +/** @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 __SEMIHOST_PRIVATE_H__ +#define __SEMIHOST_PRIVATE_H__ + +typedef struct { + CHAR8 *FileName; + UINT32 Mode; + UINT32 NameLength; +} SEMIHOST_FILE_OPEN_BLOCK; + +typedef struct { + UINT32 Handle; + VOID *Buffer; + UINT32 Length; +} SEMIHOST_FILE_READ_WRITE_BLOCK; + +typedef struct { + UINT32 Handle; + UINT32 Location; +} SEMIHOST_FILE_SEEK_BLOCK; + +typedef struct { + CHAR8 *FileName; + UINT32 NameLength; +} SEMIHOST_FILE_REMOVE_BLOCK; + +typedef struct { + CHAR8 *CommandLine; + UINT32 CommandLength; +} SEMIHOST_SYSTEM_BLOCK; + +#ifdef __CC_ARM + +#if defined(__thumb__) +#define SWI 0xAB +#else +#define SWI 0x123456 +#endif + +#define SEMIHOST_SUPPORTED TRUE + +__swi(SWI) +INT32 +_Semihost_SYS_OPEN( + IN UINTN SWI_0x01, + IN SEMIHOST_FILE_OPEN_BLOCK *OpenBlock + ); + +__swi(SWI) +INT32 +_Semihost_SYS_CLOSE( + IN UINTN SWI_0x02, + IN UINT32 *Handle + ); + +__swi(SWI) +VOID +_Semihost_SYS_WRITEC( + IN UINTN SWI_0x03, + IN CHAR8 *Character + ); + +__swi(SWI) +VOID +_Semihost_SYS_WRITE0( + IN UINTN SWI_0x04, + IN CHAR8 *String + ); + +__swi(SWI) +UINT32 +_Semihost_SYS_WRITE( + IN UINTN SWI_0x05, + IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *WriteBlock + ); + +__swi(SWI) +UINT32 +_Semihost_SYS_READ( + IN UINTN SWI_0x06, + IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *ReadBlock + ); + +__swi(SWI) +CHAR8 +_Semihost_SYS_READC( + IN UINTN SWI_0x07, + IN UINTN Zero + ); + +__swi(SWI) +INT32 +_Semihost_SYS_SEEK( + IN UINTN SWI_0x0A, + IN SEMIHOST_FILE_SEEK_BLOCK *SeekBlock + ); + +__swi(SWI) +INT32 +_Semihost_SYS_FLEN( + IN UINTN SWI_0x0C, + IN UINT32 *Handle + ); + +__swi(SWI) +UINT32 +_Semihost_SYS_REMOVE( + IN UINTN SWI_0x0E, + IN SEMIHOST_FILE_REMOVE_BLOCK *RemoveBlock + ); + +__swi(SWI) +UINT32 +_Semihost_SYS_SYSTEM( + IN UINTN SWI_0x12, + IN SEMIHOST_SYSTEM_BLOCK *SystemBlock + ); + +#define Semihost_SYS_OPEN(OpenBlock) _Semihost_SYS_OPEN(0x01, OpenBlock) +#define Semihost_SYS_CLOSE(Handle) _Semihost_SYS_CLOSE(0x02, Handle) +#define Semihost_SYS_WRITE0(String) _Semihost_SYS_WRITE0(0x04, String) +#define Semihost_SYS_WRITEC(Character) _Semihost_SYS_WRITEC(0x03, Character) +#define Semihost_SYS_WRITE(WriteBlock) _Semihost_SYS_WRITE(0x05, WriteBlock) +#define Semihost_SYS_READ(ReadBlock) _Semihost_SYS_READ(0x06, ReadBlock) +#define Semihost_SYS_READC() _Semihost_SYS_READC(0x07, 0) +#define Semihost_SYS_SEEK(SeekBlock) _Semihost_SYS_SEEK(0x0A, SeekBlock) +#define Semihost_SYS_FLEN(Handle) _Semihost_SYS_FLEN(0x0C, Handle) +#define Semihost_SYS_REMOVE(RemoveBlock) _Semihost_SYS_REMOVE(0x0E, RemoveBlock) +#define Semihost_SYS_SYSTEM(SystemBlock) _Semihost_SYS_SYSTEM(0x12, SystemBlock) + +#else // __CC_ARM + +#define SEMIHOST_SUPPORTED FALSE + +#define Semihost_SYS_OPEN(OpenBlock) (-1) +#define Semihost_SYS_CLOSE(Handle) (-1) +#define Semihost_SYS_WRITE0(String) +#define Semihost_SYS_WRITEC(Character) +#define Semihost_SYS_WRITE(WriteBlock) (0) +#define Semihost_SYS_READ(ReadBlock) ((ReadBlock)->Length) +#define Semihost_SYS_READC() ('x') +#define Semihost_SYS_SEEK(SeekBlock) (-1) +#define Semihost_SYS_FLEN(Handle) (-1) +#define Semihost_SYS_REMOVE(RemoveBlock) (-1) +#define Semihost_SYS_SYSTEM(SystemBlock) (-1) + +#endif // __CC_ARM + +#endif //__SEMIHOST_PRIVATE_H__ diff --git a/ArmPkg/Library/SemihostLib/SemihostLib.inf b/ArmPkg/Library/SemihostLib/SemihostLib.inf new file mode 100644 index 0000000000..cb278083c0 --- /dev/null +++ b/ArmPkg/Library/SemihostLib/SemihostLib.inf @@ -0,0 +1,32 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SemihostLib
+ FILE_GUID = C40D08BA-DB7B-4F07-905A-C5FE4B5AF987
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SemihostLib
+
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = ARM
+#
+[Sources.ARM]
+ Arm/SemihostLib.c
+
+
+[Packages] + MdePkg/MdePkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses] + BaseLib
+
+[Protocols]
+
+[Guids]
+
+[Pcd]
+
\ No newline at end of file diff --git a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c new file mode 100644 index 0000000000..060ba6bf98 --- /dev/null +++ b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.c @@ -0,0 +1,626 @@ +/** @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 <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UncachedMemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ArmLib.h>
+#include <Protocol/Cpu.h>
+
+EFI_PHYSICAL_ADDRESS
+ConvertToPhysicalAddress (
+ IN VOID *VirtualAddress
+ )
+{
+ UINTN UncachedMemoryMask = (UINTN)PcdGet64(PcdArmUncachedMemoryMask);
+ UINTN PhysicalAddress;
+
+ PhysicalAddress = (UINTN)VirtualAddress & ~UncachedMemoryMask;
+
+ return (EFI_PHYSICAL_ADDRESS)PhysicalAddress;
+}
+
+VOID *
+ConvertToCachedAddress (
+ IN VOID *Address
+ )
+{
+ return (VOID *)(UINTN)ConvertToPhysicalAddress(Address);
+}
+
+VOID *
+ConvertToUncachedAddress (
+ IN VOID *Address
+ )
+{
+ UINTN UncachedMemoryMask = (UINTN)PcdGet64(PcdArmUncachedMemoryMask);
+ UINTN UncachedAddress;
+
+ UncachedAddress = (UINTN)Address | UncachedMemoryMask;
+
+ return (VOID *)UncachedAddress;
+}
+
+VOID
+FlushCache (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN UINTN Size
+ )
+{
+ EFI_CPU_ARCH_PROTOCOL *Cpu;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = Cpu->FlushDataCache(Cpu, Address, Size, EfiCpuFlushTypeWriteBackInvalidate);
+ ASSERT_EFI_ERROR(Status);
+}
+
+VOID *
+UncachedInternalAllocatePages (
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Memory;
+
+ if (Pages == 0) {
+ return NULL;
+ }
+
+ Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
+ if (EFI_ERROR (Status)) {
+ Memory = 0;
+ }
+
+ if (Memory != 0) {
+ FlushCache(Memory, EFI_PAGES_TO_SIZE(Pages));
+ Memory = (EFI_PHYSICAL_ADDRESS)(UINTN)ConvertToUncachedAddress((VOID *)(UINTN)Memory);
+ }
+
+ return (VOID *) (UINTN) Memory;
+}
+
+VOID *
+EFIAPI
+UncachedAllocatePages (
+ IN UINTN Pages
+ )
+{
+ return UncachedInternalAllocatePages (EfiBootServicesData, Pages);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateRuntimePages (
+ IN UINTN Pages
+ )
+{
+ return UncachedInternalAllocatePages (EfiRuntimeServicesData, Pages);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateReservedPages (
+ IN UINTN Pages
+ )
+{
+ return UncachedInternalAllocatePages (EfiReservedMemoryType, Pages);
+}
+
+VOID
+EFIAPI
+UncachedFreePages (
+ IN VOID *Buffer,
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (Pages != 0);
+
+ Buffer = ConvertToCachedAddress(Buffer);
+
+ Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
+ ASSERT_EFI_ERROR (Status);
+}
+
+VOID *
+UncachedInternalAllocateAlignedPages (
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ IN UINTN Alignment
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS Memory;
+ UINTN AlignedMemory;
+ UINTN AlignmentMask;
+ UINTN UnalignedPages;
+ UINTN RealPages;
+
+ //
+ // Alignment must be a power of two or zero.
+ //
+ ASSERT ((Alignment & (Alignment - 1)) == 0);
+
+ if (Pages == 0) {
+ return NULL;
+ }
+ if (Alignment > EFI_PAGE_SIZE) {
+ //
+ // Caculate the total number of pages since alignment is larger than page size.
+ //
+ AlignmentMask = Alignment - 1;
+ RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
+ //
+ // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
+ //
+ ASSERT (RealPages > Pages);
+
+ Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
+ UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
+ if (UnalignedPages > 0) {
+ //
+ // Free first unaligned page(s).
+ //
+ Status = gBS->FreePages (Memory, UnalignedPages);
+ ASSERT_EFI_ERROR (Status);
+ }
+ Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
+ UnalignedPages = RealPages - Pages - UnalignedPages;
+ if (UnalignedPages > 0) {
+ //
+ // Free last unaligned page(s).
+ //
+ Status = gBS->FreePages (Memory, UnalignedPages);
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+ //
+ // Do not over-allocate pages in this case.
+ //
+ Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ AlignedMemory = (UINTN) Memory;
+ }
+
+ if (AlignedMemory != 0) {
+ FlushCache(AlignedMemory, EFI_PAGES_TO_SIZE(Pages));
+ AlignedMemory = (UINTN)ConvertToUncachedAddress((VOID *)AlignedMemory);
+ }
+
+ return (VOID *) AlignedMemory;
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedPages (
+ IN UINTN Pages,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedRuntimePages (
+ IN UINTN Pages,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedReservedPages (
+ IN UINTN Pages,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);
+}
+
+VOID
+EFIAPI
+UncachedFreeAlignedPages (
+ IN VOID *Buffer,
+ IN UINTN Pages
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (Pages != 0);
+
+ Buffer = ConvertToCachedAddress(Buffer);
+
+ Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
+ ASSERT_EFI_ERROR (Status);
+}
+
+VOID *
+UncachedInternalAllocateAlignedPool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN AllocationSize,
+ IN UINTN Alignment
+ )
+{
+ VOID *RawAddress;
+ UINTN AlignedAddress;
+ UINTN AlignmentMask;
+ UINTN OverAllocationSize;
+ UINTN RealAllocationSize;
+ VOID **FreePointer;
+ UINTN DataCacheLineLength;
+ EFI_STATUS Status;
+
+ //
+ // Alignment must be a power of two or zero.
+ //
+ ASSERT ((Alignment & (Alignment - 1)) == 0);
+
+ DataCacheLineLength = ArmDataCacheLineLength();
+
+ // Alignment must be at least cache-line aligned
+ if (Alignment < DataCacheLineLength) {
+ Alignment = DataCacheLineLength;
+ }
+
+ if (Alignment == 0) {
+ AlignmentMask = Alignment;
+ } else {
+ AlignmentMask = Alignment - 1;
+ }
+
+ //
+ // Calculate the extra memory size, over-allocate memory pool and get the aligned memory address.
+ //
+ OverAllocationSize = sizeof (RawAddress) + AlignmentMask;
+ RealAllocationSize = AllocationSize + OverAllocationSize;
+ //
+ // Make sure that AllocationSize plus OverAllocationSize does not overflow.
+ //
+ ASSERT (RealAllocationSize > AllocationSize);
+
+ Status = gBS->AllocatePool (PoolType, RealAllocationSize, &RawAddress);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ AlignedAddress = ((UINTN) RawAddress + OverAllocationSize) & ~AlignmentMask;
+ //
+ // Save the original memory address just before the aligned address.
+ //
+ FreePointer = (VOID **)(AlignedAddress - sizeof (RawAddress));
+ *FreePointer = RawAddress;
+
+ if (AlignedAddress != 0) {
+ FlushCache(AlignedAddress, AllocationSize);
+ AlignedAddress = (UINTN)ConvertToUncachedAddress((VOID *)AlignedAddress);
+ }
+
+ return (VOID *) AlignedAddress;
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedPool (
+ IN UINTN AllocationSize,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedPool (EfiBootServicesData, AllocationSize, Alignment);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedRuntimePool (
+ IN UINTN AllocationSize,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedPool (EfiRuntimeServicesData, AllocationSize, Alignment);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedReservedPool (
+ IN UINTN AllocationSize,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedPool (EfiReservedMemoryType, AllocationSize, Alignment);
+}
+
+VOID *
+UncachedInternalAllocateAlignedZeroPool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN AllocationSize,
+ IN UINTN Alignment
+ )
+{
+ VOID *Memory;
+ Memory = UncachedInternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);
+ if (Memory != NULL) {
+ Memory = ZeroMem (Memory, AllocationSize);
+ }
+ return Memory;
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedZeroPool (
+ IN UINTN AllocationSize,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedZeroPool (EfiBootServicesData, AllocationSize, Alignment);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedRuntimeZeroPool (
+ IN UINTN AllocationSize,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedZeroPool (EfiRuntimeServicesData, AllocationSize, Alignment);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedReservedZeroPool (
+ IN UINTN AllocationSize,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedZeroPool (EfiReservedMemoryType, AllocationSize, Alignment);
+}
+
+VOID *
+UncachedInternalAllocateAlignedCopyPool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN AllocationSize,
+ IN CONST VOID *Buffer,
+ IN UINTN Alignment
+ )
+{
+ VOID *Memory;
+
+ ASSERT (Buffer != NULL);
+ ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
+
+ Memory = UncachedInternalAllocateAlignedPool (PoolType, AllocationSize, Alignment);
+ if (Memory != NULL) {
+ Memory = CopyMem (Memory, Buffer, AllocationSize);
+ }
+ return Memory;
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedCopyPool (
+ IN UINTN AllocationSize,
+ IN CONST VOID *Buffer,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedCopyPool (EfiBootServicesData, AllocationSize, Buffer, Alignment);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedRuntimeCopyPool (
+ IN UINTN AllocationSize,
+ IN CONST VOID *Buffer,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer, Alignment);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateAlignedReservedCopyPool (
+ IN UINTN AllocationSize,
+ IN CONST VOID *Buffer,
+ IN UINTN Alignment
+ )
+{
+ return UncachedInternalAllocateAlignedCopyPool (EfiReservedMemoryType, AllocationSize, Buffer, Alignment);
+}
+
+VOID
+EFIAPI
+UncachedFreeAlignedPool (
+ IN VOID *Buffer
+ )
+{
+ VOID *RawAddress;
+ VOID **FreePointer;
+ EFI_STATUS Status;
+
+ Buffer = ConvertToCachedAddress(Buffer);
+
+ //
+ // Get the pre-saved original address in the over-allocate pool.
+ //
+ FreePointer = (VOID **)((UINTN) Buffer - sizeof (RawAddress));
+ RawAddress = *FreePointer;
+
+ Status = gBS->FreePool (RawAddress);
+ ASSERT_EFI_ERROR (Status);
+}
+
+VOID *
+UncachedInternalAllocatePool (
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN AllocationSize
+ )
+{
+ UINTN CacheLineLength = ArmDataCacheLineLength();
+ return UncachedInternalAllocateAlignedPool(MemoryType, AllocationSize, CacheLineLength);
+}
+
+VOID *
+EFIAPI
+UncachedAllocatePool (
+ IN UINTN AllocationSize
+ )
+{
+ return UncachedInternalAllocatePool (EfiBootServicesData, AllocationSize);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateRuntimePool (
+ IN UINTN AllocationSize
+ )
+{
+ return UncachedInternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateReservedPool (
+ IN UINTN AllocationSize
+ )
+{
+ return UncachedInternalAllocatePool (EfiReservedMemoryType, AllocationSize);
+}
+
+VOID *
+UncachedInternalAllocateZeroPool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN AllocationSize
+ )
+{
+ VOID *Memory;
+
+ Memory = UncachedInternalAllocatePool (PoolType, AllocationSize);
+ if (Memory != NULL) {
+ Memory = ZeroMem (Memory, AllocationSize);
+ }
+ return Memory;
+}
+
+VOID *
+EFIAPI
+UncachedAllocateZeroPool (
+ IN UINTN AllocationSize
+ )
+{
+ return UncachedInternalAllocateZeroPool (EfiBootServicesData, AllocationSize);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateRuntimeZeroPool (
+ IN UINTN AllocationSize
+ )
+{
+ return UncachedInternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateReservedZeroPool (
+ IN UINTN AllocationSize
+ )
+{
+ return UncachedInternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);
+}
+
+VOID *
+UncachedInternalAllocateCopyPool (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN AllocationSize,
+ IN CONST VOID *Buffer
+ )
+{
+ VOID *Memory;
+
+ ASSERT (Buffer != NULL);
+ ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
+
+ Memory = UncachedInternalAllocatePool (PoolType, AllocationSize);
+ if (Memory != NULL) {
+ Memory = CopyMem (Memory, Buffer, AllocationSize);
+ }
+ return Memory;
+}
+
+VOID *
+EFIAPI
+UncachedAllocateCopyPool (
+ IN UINTN AllocationSize,
+ IN CONST VOID *Buffer
+ )
+{
+ return UncachedInternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateRuntimeCopyPool (
+ IN UINTN AllocationSize,
+ IN CONST VOID *Buffer
+ )
+{
+ return UncachedInternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
+}
+
+VOID *
+EFIAPI
+UncachedAllocateReservedCopyPool (
+ IN UINTN AllocationSize,
+ IN CONST VOID *Buffer
+ )
+{
+ return UncachedInternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);
+}
+
+VOID
+EFIAPI
+UncachedFreePool (
+ IN VOID *Buffer
+ )
+{
+ UncachedFreeAlignedPool(Buffer);
+}
+
+VOID
+EFIAPI
+UncachedSafeFreePool (
+ IN VOID *Buffer
+ )
+{
+ if (Buffer != NULL) {
+ UncachedFreePool (Buffer);
+ Buffer = NULL;
+ }
+}
+
diff --git a/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf new file mode 100644 index 0000000000..1a62eb4231 --- /dev/null +++ b/ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf @@ -0,0 +1,25 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UncachedMemoryAllocationLib
+ FILE_GUID = DC101A1A-7525-429B-84AF-EEAA630E576C
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UncachedMemoryAllocationLib
+
+[Sources.common]
+ UncachedMemoryAllocationLib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[LibraryClasses]
+ ArmLib
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdArmUncachedMemoryMask
+
\ No newline at end of file diff --git a/BeagleBoardPkg/AppleBeagleBoardPkg.dsc b/BeagleBoardPkg/AppleBeagleBoardPkg.dsc new file mode 100644 index 0000000000..251e8d563e --- /dev/null +++ b/BeagleBoardPkg/AppleBeagleBoardPkg.dsc @@ -0,0 +1,366 @@ +#/** @file +# Beagle board package. +# +# Copyright (c) 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. +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = AppleBeagleBoardPkg + PLATFORM_GUID = 1C1D4FD7-703A-4DD5-A97B-FB794921859E + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/AppleBeagleBoard + SUPPORTED_ARCHITECTURES = ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = BeagleBoardPkg/AppleBeagleBoardPkg.fdf + + +[LibraryClasses.common] + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf + + + ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf + + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + + BeagleBoardSystemLib|BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf + EfiResetSystemLib|BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf + + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + + EblCmdLib|BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf + + EfiFileLib|EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf + + + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + + SerialPortLib|BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf + SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf + + RealTimeClockLib|EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf + + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + +# +# Assume everything is fixed at build +# + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + + UsbLib|AppleCommonPkg/Library/AppleUsbLib/AppleUsbDxeLib.inf + EblAddExternalCommandLib|EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf + + UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf + + TimerLib|BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf + OmapLib|BeagleBoardPkg/Library/OmapLib/OmapLib.inf + EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf + + GdbSerialLib|BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + +[LibraryClasses.common.SEC] + ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + LzmaDecompressLib|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + +[LibraryClasses.common.PEI_CORE] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + +[LibraryClasses.common.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + +[LibraryClasses.common.DXE_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + + +[LibraryClasses.common.UEFI_APPLICATION] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + +[BuildOptions] + XCODE:*_*_ARM_ARCHCC_FLAGS == -arch armv6 -march=armv6 + XCODE:*_*_ARM_ARCHASM_FLAGS == -arch armv6 + XCODE:*_*_ARM_ARCHDLINK_FLAGS == -arch armv6 + + RVCT:*_*_ARM_ARCHCC_FLAGS == --cpu Cortex-A8 + RVCT:*_*_ARM_ARCHASM_FLAGS == --cpu Cortex-A8 + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE + + # + # Control what commands are supported from the UI + # Turn these on and off to add features or save size + # + gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE + gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE + + gEmbeddedTokenSpaceGuid.PcdCacheEnable|TRUE + + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE + gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport|FALSE + + # + # Beagle board Specific PCDs + # + +[PcdsFixedAtBuild.common] + gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"AppleEFI" + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0 + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000 + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000004 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + + gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|"" + gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07 + gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000 + + gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|0 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize|0 + +# +# Optional feature to help prevent EFI memory map fragments +# Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob +# Values are in EFI Pages (4K). DXE Core will make sure that +# at least this much of each type of memory can be allocated +# from a single memory range. This way you only end up with +# maximum of two fragements for each type in the memory map +# (the memory used, and the free memory that was prereserved +# but not used). +# + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|80 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|40 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|400 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|3000 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|10 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0 + + +# +# Beagle board Specific PCDs +# + gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|0x80001000 + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0x87FE0000 # stack at top of memory + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|0x20000 # 128K stack + gBeagleBoardTokenSpaceGuid.PcdBeagleBoardIRAMFullSize|0x00000000 + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0x80000000 + gArmTokenSpaceGuid.PcdCpuResetAddress|0x80008000 + + gBeagleBoardTokenSpaceGuid.PcdBeagleGpmcOffset|0x6E000000 + gBeagleBoardTokenSpaceGuid.PcdBeagleMMCHS1Base|0x4809C000 + + # Console + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart|3 + + # Timers +# gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|OMAP3530_GPTIMER3 + gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|3 +# gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|OMAP3530_GPTIMER4 + gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|4 + gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds|77 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterFrequencyInHz|13000000 + + # + # ARM Pcds + # + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000040000000 + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform +# +################################################################################ +[Components.common] + +# +# SEC +# + BeagleBoardPkg/Sec/Sec.inf + +# +# DXE +# + MdeModulePkg/Core/Dxe/DxeMain.inf { + <LibraryClasses> + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } + + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + + EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + + # + # Semi-hosting filesystem + # + ArmPkg/Filesystem/SemihostFs/SemihostFs.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + EnhancedFat/FatDxe/FatDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # USB + # + BeagleBoardPkg/PciEmulation/PciEmulation.inf + AppleCommonPkg/Bus/Pci/EhciDxe/Ehci.inf + AppleCommonPkg/Bus/Usb/UsbBotDxe/UsbBot.inf + AppleCommonPkg/Bus/Usb/UsbCbiDxe/Cbi0/UsbCbi0.inf + AppleCommonPkg/Bus/Usb/UsbCbiDxe/Cbi1/UsbCbi1.inf + AppleCommonPkg/Bus/Usb/UsbBusDxe/UsbBus.inf + AppleCommonPkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorage.inf + + #NOTE: Open source EHCI stack doesn't work on Beagleboard. + #NOTE: UsbBus and UsbMassStorage don't work using iPhond SDK tool chain. + #MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + #MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + #MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # Nand Flash + # + BeagleBoardPkg/Flash/Flash.inf + + # + # MMC/SD + # + BeagleBoardPkg/MMCHSDxe/MMCHS.inf + + # + # I2C + # + BeagleBoardPkg/SmbusDxe/Smbus.inf + + # + # SoC Drivers + # + BeagleBoardPkg/Gpio/Gpio.inf + BeagleBoardPkg/InterruptDxe/InterruptDxe.inf + BeagleBoardPkg/TimerDxe/TimerDxe.inf + + # + # Power IC + # + BeagleBoardPkg/TPS65950Dxe/TPS65950.inf + + # + # Application + # + EmbeddedPkg/Ebl/Ebl.inf + + # + # Bds + # + BeagleBoardPkg/Bds/Bds.inf + + # + # Gdb Stub + # + EmbeddedPkg/GdbStub/GdbStub.inf + ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + diff --git a/BeagleBoardPkg/AppleBeagleBoardPkg.fdf b/BeagleBoardPkg/AppleBeagleBoardPkg.fdf new file mode 100644 index 0000000000..9852dfdd3f --- /dev/null +++ b/BeagleBoardPkg/AppleBeagleBoardPkg.fdf @@ -0,0 +1,303 @@ +# FLASH layout file for Beagle board. +# +# Copyright (c) 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. +# + +################################################################################ +# +# FD Section +# The [FD] Section is made up of the definition statements and a +# description of what goes into the Flash Device Image. Each FD section +# defines one flash "device" image. A flash device image may be one of +# the following: Removable media bootable image (like a boot floppy +# image,) an Option ROM image (that would be "flashed" into an add-in +# card,) a System "Flash" image (that would be burned into a system's +# flash) or an Update ("Capsule") image that will be used to update and +# existing system flash. +# +################################################################################ + + +[FD.BeagleBoard_EFI] +BaseAddress = 0x80008000|gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress #The base address of the FLASH Device. +Size = 0x00080000|gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize #The size in bytes of the FLASH Device +ErasePolarity = 1 +BlockSize = 0x40 +NumBlocks = 0x2000 + +################################################################################ +# +# Following are lists of FD Region layout which correspond to the locations of different +# images within the flash device. +# +# Regions must be defined in ascending order and may not overlap. +# +# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by +# the pipe "|" character, followed by the size of the region, also in hex with the leading +# "0x" characters. Like: +# Offset|Size +# PcdOffsetCName|PcdSizeCName +# RegionType <FV, DATA, or FILE> +# +################################################################################ + +# 512 bytes of configuration header & 8 bytes of image header +0x00000000|0x00000208 + +0x00000208|0x0007FDF8 +gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize +FV = FVMAIN_COMPACT + +################################################################################ +# +# FV Section +# +# [FV] section is used to define what components or modules are placed within a flash +# device file. This section also defines order the components and modules are positioned +# within the image. The [FV] section consists of define statements, set statements and +# module statements. +# +################################################################################ + +[FV.FvMain] +BlockSize = 0x40 +NumBlocks = 0x9000 +FvAlignment = 8 #FV alignment and FV attributes setting. +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + # + # PI DXE Drivers producing Architectural Protocols (EFI Services) + # + INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf + + INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + INF EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + + INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + + INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + INF EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + + # + # Semi-hosting filesystem + # + INF ArmPkg/Filesystem/SemihostFs/SemihostFs.inf + + # + # Nand Flash + # + INF BeagleBoardPkg/Flash/Flash.inf + + # + # MMC/SD + # + INF BeagleBoardPkg/MMCHSDxe/MMCHS.inf + + # + # I2C + # + INF BeagleBoardPkg/SmbusDxe/Smbus.inf + + # + # SoC Drivers + # + INF BeagleBoardPkg/Gpio/Gpio.inf + INF BeagleBoardPkg/InterruptDxe/InterruptDxe.inf + INF BeagleBoardPkg/TimerDxe/TimerDxe.inf + + # + # Power IC + # + INF BeagleBoardPkg/TPS65950Dxe/TPS65950.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + INF EnhancedFat/FatDxe/FatDxe.inf + INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # USB Support + # + + INF BeagleBoardPkg/PciEmulation/PciEmulation.inf + INF AppleCommonPkg/Bus/Pci/EhciDxe/Ehci.inf + INF AppleCommonPkg/Bus/Usb/UsbBotDxe/UsbBot.inf + INF AppleCommonPkg/Bus/Usb/UsbCbiDxe/Cbi0/UsbCbi0.inf + INF AppleCommonPkg/Bus/Usb/UsbCbiDxe/Cbi1/UsbCbi1.inf + INF AppleCommonPkg/Bus/Usb/UsbBusDxe/UsbBus.inf + INF AppleCommonPkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorage.inf + + + #NOTE: Open source EHCI stack doesn't work on Beagleboard. + #NOTE: UsbBus and UsbMassStorage don't work using iPhond SDK tool chain. + #INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + #INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + #INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # UEFI application (Shell Embedded Boot Loader) + # + INF EmbeddedPkg/Ebl/Ebl.inf + + + # + # Bds + # + INF BeagleBoardPkg/Bds/Bds.inf + + # + # Gdb Stub + # + #INF ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + #INF ApplePkg/Universal/GdbStub/GdbStub.inf + + +[FV.FVMAIN_COMPACT] +FvAlignment = 8 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + INF BeagleBoardPkg/Sec/Sec.inf + INF MdeModulePkg/Core/Dxe/DxeMain.inf + + FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } + } + + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + + +############################################################################ +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section # +############################################################################ +# +#[Rule.Common.DXE_DRIVER] +# FILE DRIVER = $(NAMED_GUID) { +# DXE_DEPEX DXE_DEPEX Optional |.depex +# COMPRESS PI_STD { +# GUIDED { +# PE32 PE32 |.efi +# UI STRING="$(MODULE_NAME)" Optional +# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) +# } +# } +# } +# +############################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED { + TE TE Align = 8 |.efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + TE TE |.efi + UI STRING ="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM.TIANOCOMPRESSED] + FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 { + PEI_DEPEX PEI_DEPEX Optional |.depex + GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + } + + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + UI STRING ="$(MODULE_NAME)" Optional + PE32 PE32 |.efi + } diff --git a/BeagleBoardPkg/Bds/Bds.inf b/BeagleBoardPkg/Bds/Bds.inf new file mode 100644 index 0000000000..18e019147b --- /dev/null +++ b/BeagleBoardPkg/Bds/Bds.inf @@ -0,0 +1,70 @@ +#%HEADER%
+#/** @file
+#
+# Component discription file for Bds module
+#
+# Copyright (c) 2009 Apple, Inc. All rights reserved.
+#
+# This document is the property of Apple, Inc.
+# It is considered confidential and proprietary.
+#
+# This document may not be reproduced or transmitted in any form,
+# in whole or in part, without the express written permission of
+# Apple, Inc.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BeagleBoardBds
+ FILE_GUID = 934431fe-5745-402e-913d-17b4434eb0f3
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = BdsInitialize
+
+[Sources.common]
+ BdsEntry.c
+ FirmwareVolume.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ DevicePathLib
+ BaseLib
+ HobLib
+ UefiRuntimeServicesTableLib
+ ReportStatusCodeLib
+ PerformanceLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ UefiDriverEntryPoint
+
+[Guids]
+
+
+[Protocols]
+ gEfiBdsArchProtocolGuid
+ gEfiSimpleTextInProtocolGuid
+ gEfiSimpleTextOutProtocolGuid
+ gEfiSerialIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
+ gEfiUsbIoProtocolGuid
+ gEfiFirmwareVolume2ProtocolGuid
+
+
+[FeaturePcd]
+
+[FixedPcd]
+ gEmbeddedTokenSpaceGuid.PcdPrePiStackSize
+
+[Depex]
+ TRUE
diff --git a/BeagleBoardPkg/Bds/BdsEntry.c b/BeagleBoardPkg/Bds/BdsEntry.c new file mode 100644 index 0000000000..05afd190dd --- /dev/null +++ b/BeagleBoardPkg/Bds/BdsEntry.c @@ -0,0 +1,240 @@ +/** @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;
+ EFI_HANDLE FvHandle;
+ EFI_HANDLE ImageHandle;
+ EFI_HANDLE UsbDeviceHandle;
+ EFI_GUID NameGuid;
+ UINTN Size;
+ UINTN HandleCount;
+ UINTN OldHandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *LoadImageDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *FileSystemDevicePath;
+
+ //
+ // Now do the EFI stuff
+ //
+ Size = 0x100;
+ gST->FirmwareVendor = AllocateRuntimePool (Size);
+ ASSERT (gST->FirmwareVendor != NULL);
+
+ UnicodeSPrint (gST->FirmwareVendor, Size, L"BeagleBoard EFI %a %a", __DATE__, __TIME__);
+
+ //
+ // 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;
+
+ gST->ConOut->OutputString (gST->ConOut, L"BDS: Console Started!!!!\n\r");
+ 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.
+ //
+
+ //
+ //Perform Connect
+ //
+ HandleCount = 0;
+ while (1) {
+ OldHandleCount = HandleCount;
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (HandleCount == OldHandleCount) {
+ break;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+ }
+
+ //Locate handles for SimpleFileSystem protocol
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR(Status)) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ //Get the device path
+ FileSystemDevicePath = DevicePathFromHandle(HandleBuffer[Index]);
+ if (FileSystemDevicePath == NULL) {
+ continue;
+ }
+
+ //Check if UsbIo is on any handles in the device path.
+ Status = gBS->LocateDevicePath(&gEfiUsbIoProtocolGuid, &FileSystemDevicePath, &UsbDeviceHandle);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ //Check if Usb stick has a magic EBL file.
+ LoadImageDevicePath = FileDevicePath(HandleBuffer[Index], L"Ebl.efi");
+ Status = gBS->LoadImage (TRUE, gImageHandle, LoadImageDevicePath, NULL, 0, &ImageHandle);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ //Boot to Shell on USB stick.
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ }
+ }
+
+ //
+ // 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)) {
+
+ //Boot to Shell.
+ Status = LoadPeCoffSectionFromFv (FvHandle, &NameGuid);
+
+ if (EFI_ERROR(Status)) {
+ DEBUG((EFI_D_ERROR, "Boot from Shell failed. Status: %r\n", Status));
+ }
+ }
+
+ //
+ // EFI does not define the behaviour 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 (EfiResetShutdown, 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;
+}
+
+
diff --git a/BeagleBoardPkg/Bds/BdsEntry.h b/BeagleBoardPkg/Bds/BdsEntry.h new file mode 100644 index 0000000000..21e49498cf --- /dev/null +++ b/BeagleBoardPkg/Bds/BdsEntry.h @@ -0,0 +1,65 @@ +/** @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 <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+
+#include <Protocol/Bds.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/EmbeddedDevice.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/UsbIo.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
+
diff --git a/BeagleBoardPkg/Bds/FirmwareVolume.c b/BeagleBoardPkg/Bds/FirmwareVolume.c new file mode 100644 index 0000000000..f08de5767a --- /dev/null +++ b/BeagleBoardPkg/Bds/FirmwareVolume.c @@ -0,0 +1,150 @@ +/** @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) 2009 Apple, Inc. All rights reserved.
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+
+ This document is the property of Apple, Inc.
+ It is considered confidential and proprietary.
+
+ This document may not be reproduced or transmitted in any form,
+ in whole or in part, without the express written permission of
+ Apple, Inc.
+
+**/
+
+#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) {
+ DEBUG ((DEBUG_ERROR, "UiString %s\n", UiString));
+ 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);
+ ASSERT (Key != NULL);
+ ZeroMem (Key, 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) == 0) {
+ //
+ // 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_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HANDLE ImageHandle;
+
+ DevicePath = FvFileDevicePath (FvHandle, NameGuid);
+
+ Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, NULL, 0, &ImageHandle);
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ }
+
+ return Status;
+}
+
diff --git a/BeagleBoardPkg/BeagleBoardPkg.dec b/BeagleBoardPkg/BeagleBoardPkg.dec new file mode 100644 index 0000000000..7a92f94a21 --- /dev/null +++ b/BeagleBoardPkg/BeagleBoardPkg.dec @@ -0,0 +1,65 @@ +#%HEADER% +#/** @file +# Beagle board package. +# +# Copyright (c) 2009, Apple Inc. +# +# All rights reserved. +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = BeagleBoardPkg + PACKAGE_GUID = 6eba6648-d853-4eb3-9761-528b82d5ab04 + PACKAGE_VERSION = 0.1 + +################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################ +[Includes.common] + Include # Root include for the package + +[Guids.common] + gBeagleBoardTokenSpaceGuid = { 0x6834fe45, 0x4aee, 0x4fc6, { 0xbc, 0xb5, 0xff, 0x45, 0xb7, 0xa8, 0x71, 0xe2 } } + +#[PcdsEnumerations.common] +# OMAP3530_GPTIMER: +# OMAP3530_GPTIMER1|1 +# OMAP3530_GPTIMER2|2 +# OMAP3530_GPTIMER3|3 +# OMAP3530_GPTIMER4|4 +# OMAP3530_GPTIMER5|5 +# OMAP3530_GPTIMER6|6 +# OMAP3530_GPTIMER7|7 +# OMAP3530_GPTIMER8|8 +# OMAP3530_GPTIMER9|9 +# OMAP3530_GPTIMER10|10 +# OMAP3530_GPTIMER11|11 +# OMAP3530_GPTIMER12|12 + +[PcdsFeatureFlag.common] + +[PcdsFixedAtBuild.common] + gBeagleBoardTokenSpaceGuid.PcdBeagleBoardIRAMFullSize|0x00000000|UINT32|0x00000201 + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart|3|UINT32|0x00000202 + gBeagleBoardTokenSpaceGuid.PcdBeagleGpmcOffset|0x00000000|UINT32|0x00000203 + gBeagleBoardTokenSpaceGuid.PcdBeagleMMCHS1Base|0x00000000|UINT32|0x00000204 +# gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|OMAP3530_GPTIMER3|OMAP3530_GPTIMER|0x00000205 + gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|3|UINT32|0x00000205 +# gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|OMAP3530_GPTIMER4|OMAP3530_GPTIMER|0x00000206 + gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|4|UINT32|0x00000206 + diff --git a/BeagleBoardPkg/BeagleBoardPkg.dsc b/BeagleBoardPkg/BeagleBoardPkg.dsc new file mode 100644 index 0000000000..a0d7a77172 --- /dev/null +++ b/BeagleBoardPkg/BeagleBoardPkg.dsc @@ -0,0 +1,415 @@ +#/** @file +# Beagle board package. +# +# Copyright (c) 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. +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = BeagleBoardPkg + PLATFORM_GUID = 91fa6c28-33df-46ac-aee6-292d6811ea31 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/BeagleBoard + SUPPORTED_ARCHITECTURES = ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = BeagleBoardPkg/BeagleBoardPkg.fdf + DEFINE TARGET_HACK = DEBUG + + +[LibraryClasses.common] +!if TARGET_HACK == DEBUG + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!else + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf +!endif + + + ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLib.inf + + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + + BeagleBoardSystemLib|BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf + EfiResetSystemLib|BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf + + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + + EblCmdLib|BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf + + EfiFileLib|EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf + + + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + + SerialPortLib|BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf + SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf + + RealTimeClockLib|EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf + + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + +# +# Assume everything is fixed at build +# + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + EblAddExternalCommandLib|EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf + + UncachedMemoryAllocationLib|ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf + + TimerLib|BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf + OmapLib|BeagleBoardPkg/Library/OmapLib/OmapLib.inf + EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf + + GdbSerialLib|BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf + + +[LibraryClasses.common.SEC] + ArmLib|ArmPkg/Library/ArmLib/ArmCortexA/ArmCortexArmLibPrePi.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + LzmaDecompressLib|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + +[LibraryClasses.common.PEI_CORE] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + +[LibraryClasses.common.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + +[LibraryClasses.common.DXE_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + + +[LibraryClasses.common.UEFI_APPLICATION] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + +[BuildOptions] + XCODE:*_*_ARM_ARCHCC_FLAGS == -arch armv6 -march=armv6 + XCODE:*_*_ARM_ARCHASM_FLAGS == -arch armv6 + XCODE:*_*_ARM_ARCHDLINK_FLAGS == -arch armv6 + + RVCT:*_*_ARM_ARCHCC_FLAGS == --cpu Cortex-A8 + RVCT:*_*_ARM_ARCHASM_FLAGS == --cpu Cortex-A8 + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE + + # + # Control what commands are supported from the UI + # Turn these on and off to add features or save size + # + gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE + gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE + + gEmbeddedTokenSpaceGuid.PcdCacheEnable|TRUE + + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE + gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport|FALSE + + # + # Beagle board Specific PCDs + # + +[PcdsFixedAtBuild.common] + gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"BeagleEdk2" + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0 + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000 + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320 + +# DEBUG_ASSERT_ENABLED 0x01 + +# DEBUG_PRINT_ENABLED 0x02 + +# DEBUG_CODE_ENABLED 0x04 + +# CLEAR_MEMORY_ENABLED 0x08 + +# ASSERT_BREAKPOINT_ENABLED 0x10 + +# ASSERT_DEADLOOP_ENABLED 0x20 + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f + +# DEBUG_INIT 0x00000001 // Initialization + +# DEBUG_WARN 0x00000002 // Warnings + +# DEBUG_LOAD 0x00000004 // Load events + +# DEBUG_FS 0x00000008 // EFI File system + +# DEBUG_POOL 0x00000010 // Alloc & Free's + +# DEBUG_PAGE 0x00000020 // Alloc & Free's + +# DEBUG_INFO 0x00000040 // Verbose + +# DEBUG_DISPATCH 0x00000080 // PEI/DXE Dispatchers + +# DEBUG_VARIABLE 0x00000100 // Variable + +# DEBUG_BM 0x00000400 // Boot Manager + +# DEBUG_BLKIO 0x00001000 // BlkIo Driver + +# DEBUG_NET 0x00004000 // SNI Driver + +# DEBUG_UNDI 0x00010000 // UNDI Driver + +# DEBUG_LOADFILE 0x00020000 // UNDI Driver + +# DEBUG_EVENT 0x00080000 // Event messages + +# DEBUG_ERROR 0x80000000 // Error + + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000004 + + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + + gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|"" + gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07 + gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000 + + gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|0 + gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize|0 + +# +# Optional feature to help prevent EFI memory map fragments +# Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob +# Values are in EFI Pages (4K). DXE Core will make sure that +# at least this much of each type of memory can be allocated +# from a single memory range. This way you only end up with +# maximum of two fragements for each type in the memory map +# (the memory used, and the free memory that was prereserved +# but not used). +# + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|80 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|40 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|400 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|3000 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|10 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0 + + +# +# Beagle board Specific PCDs +# + gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|0x80001000 + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0x87FE0000 # stack at top of memory + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|0x20000 # 128K stack + gBeagleBoardTokenSpaceGuid.PcdBeagleBoardIRAMFullSize|0x00000000 + gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0x80000000 + gArmTokenSpaceGuid.PcdCpuResetAddress|0x80008000 + + gBeagleBoardTokenSpaceGuid.PcdBeagleGpmcOffset|0x6E000000 + gBeagleBoardTokenSpaceGuid.PcdBeagleMMCHS1Base|0x4809C000 + + # Console + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart|3 + + # Timers +# gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|OMAP3530_GPTIMER3 + gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer|3 +# gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|OMAP3530_GPTIMER4 + gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer|4 + gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds|77 + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterFrequencyInHz|13000000 + + # + # ARM Pcds + # + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000040000000 + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform +# +################################################################################ +[Components.common] + +# +# SEC +# + BeagleBoardPkg/Sec/Sec.inf + +# +# DXE +# + MdeModulePkg/Core/Dxe/DxeMain.inf { + <LibraryClasses> + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf + NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + } + + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + + EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + + # + # Semi-hosting filesystem + # + ArmPkg/Filesystem/SemihostFs/SemihostFs.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + FatPkg/EnhancedFatDxe/Fat.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # USB + # + BeagleBoardPkg/PciEmulation/PciEmulation.inf + + #NOTE: Open source EHCI stack doesn't work on Beagleboard. + #NOTE: UsbBus and UsbMassStorage don't work using iPhone SDK tool chain. + MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf { + <PcdsFixedAtBuild> + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x800fffff + } + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # Nand Flash + # + BeagleBoardPkg/Flash/Flash.inf + + # + # MMC/SD + # + BeagleBoardPkg/MMCHSDxe/MMCHS.inf + + # + # I2C + # + BeagleBoardPkg/SmbusDxe/Smbus.inf + + # + # SoC Drivers + # + BeagleBoardPkg/Gpio/Gpio.inf + BeagleBoardPkg/InterruptDxe/InterruptDxe.inf + BeagleBoardPkg/TimerDxe/TimerDxe.inf + + # + # Power IC + # + BeagleBoardPkg/TPS65950Dxe/TPS65950.inf + + # + # Application + # + EmbeddedPkg/Ebl/Ebl.inf + + # + # Bds + # + BeagleBoardPkg/Bds/Bds.inf + + # + # Gdb Stub + # + EmbeddedPkg/GdbStub/GdbStub.inf + ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + diff --git a/BeagleBoardPkg/BeagleBoardPkg.fdf b/BeagleBoardPkg/BeagleBoardPkg.fdf new file mode 100644 index 0000000000..d29650497e --- /dev/null +++ b/BeagleBoardPkg/BeagleBoardPkg.fdf @@ -0,0 +1,296 @@ +# FLASH layout file for Beagle board. +# +# Copyright (c) 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. +# + +################################################################################ +# +# FD Section +# The [FD] Section is made up of the definition statements and a +# description of what goes into the Flash Device Image. Each FD section +# defines one flash "device" image. A flash device image may be one of +# the following: Removable media bootable image (like a boot floppy +# image,) an Option ROM image (that would be "flashed" into an add-in +# card,) a System "Flash" image (that would be burned into a system's +# flash) or an Update ("Capsule") image that will be used to update and +# existing system flash. +# +################################################################################ + + +[FD.BeagleBoard_EFI] +BaseAddress = 0x80008000|gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress #The base address of the FLASH Device. +Size = 0x00080000|gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize #The size in bytes of the FLASH Device +ErasePolarity = 1 +BlockSize = 0x40 +NumBlocks = 0x2000 + +################################################################################ +# +# Following are lists of FD Region layout which correspond to the locations of different +# images within the flash device. +# +# Regions must be defined in ascending order and may not overlap. +# +# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by +# the pipe "|" character, followed by the size of the region, also in hex with the leading +# "0x" characters. Like: +# Offset|Size +# PcdOffsetCName|PcdSizeCName +# RegionType <FV, DATA, or FILE> +# +################################################################################ + +# 512 bytes of configuration header & 8 bytes of image header +0x00000000|0x00000208 + +0x00000208|0x0007FDF8 +gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize +FV = FVMAIN_COMPACT + +################################################################################ +# +# FV Section +# +# [FV] section is used to define what components or modules are placed within a flash +# device file. This section also defines order the components and modules are positioned +# within the image. The [FV] section consists of define statements, set statements and +# module statements. +# +################################################################################ + +[FV.FvMain] +BlockSize = 0x40 +NumBlocks = 0x9000 +FvAlignment = 8 #FV alignment and FV attributes setting. +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + # + # PI DXE Drivers producing Architectural Protocols (EFI Services) + # + INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf + + INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + INF EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + + INF EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + + INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + INF EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + + # + # Semi-hosting filesystem + # + INF ArmPkg/Filesystem/SemihostFs/SemihostFs.inf + + # + # Nand Flash + # + INF BeagleBoardPkg/Flash/Flash.inf + + # + # MMC/SD + # + INF BeagleBoardPkg/MMCHSDxe/MMCHS.inf + + # + # I2C + # + INF BeagleBoardPkg/SmbusDxe/Smbus.inf + + # + # SoC Drivers + # + INF BeagleBoardPkg/Gpio/Gpio.inf + INF BeagleBoardPkg/InterruptDxe/InterruptDxe.inf + INF BeagleBoardPkg/TimerDxe/TimerDxe.inf + + # + # Power IC + # + INF BeagleBoardPkg/TPS65950Dxe/TPS65950.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + INF FatPkg/EnhancedFatDxe/Fat.inf + INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # USB Support + # + + INF BeagleBoardPkg/PciEmulation/PciEmulation.inf + + #NOTE: Open source EHCI stack doesn't work on Beagleboard. + #NOTE: UsbBus and UsbMassStorage don't work using iPhond SDK tool chain. + INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf + INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + + # + # UEFI application (Shell Embedded Boot Loader) + # + INF EmbeddedPkg/Ebl/Ebl.inf + + + # + # Bds + # + INF BeagleBoardPkg/Bds/Bds.inf + + # + # Gdb Stub + # + #INF ArmPkg/Drivers/DebugSupportDxe/DebugSupportDxe.inf + #INF ApplePkg/Universal/GdbStub/GdbStub.inf + + +[FV.FVMAIN_COMPACT] +FvAlignment = 8 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + INF BeagleBoardPkg/Sec/Sec.inf + INF MdeModulePkg/Core/Dxe/DxeMain.inf + + FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } + } + + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + + +############################################################################ +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section # +############################################################################ +# +#[Rule.Common.DXE_DRIVER] +# FILE DRIVER = $(NAMED_GUID) { +# DXE_DEPEX DXE_DEPEX Optional |.depex +# COMPRESS PI_STD { +# GUIDED { +# PE32 PE32 |.efi +# UI STRING="$(MODULE_NAME)" Optional +# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) +# } +# } +# } +# +############################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED { + TE TE Align = 8 |.efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + TE TE |.efi + UI STRING ="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM.TIANOCOMPRESSED] + FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 { + PEI_DEPEX PEI_DEPEX Optional |.depex + GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + } + + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + } + + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + UI STRING ="$(MODULE_NAME)" Optional + PE32 PE32 |.efi + } diff --git a/BeagleBoardPkg/ConfigurationHeader.dat b/BeagleBoardPkg/ConfigurationHeader.dat new file mode 100644 index 0000000000..5f6897e306 --- /dev/null +++ b/BeagleBoardPkg/ConfigurationHeader.dat @@ -0,0 +1,41 @@ +PRM_CLKSRC_CTRL=0x00000080 +PRM_CLKSEL=0x00000003 +CM_CLKSEL1_EMU=0x03020A50 +CM_CLKSEL_CORE=0x0000030A +CM_CLKSEL_WKUP=0x00000015 +CM_CLKEN_PLL_DPLL3=0x00370037 +CM_AUTOIDLE_PLL_DPLL3=0x00000000 +CM_CLKSEL1_PLL=0x094C0C00 +CM_CLKEN_PLL_DPLL4=0x00370037 +CM_AUTOIDLE_PLL_DPLL4=0x00000000 +CM_CLKSEL2_PLL=0x0001B00C +CM_CLKSEL3_PLL=0x00000009 +CM_CLKEN_PLL_MPU=0x00000037 +CM_AUTOIDLE_PLL_MPU=0x00000000 +CM_CLKSEL1_PLL_MPU=0x0011F40C +CM_CLKSEL2_PLL_MPU=0x00000001 +CM_CLKSTCTRL_MPU=0x00000000 +SDRC_SYSCONFIG_LSB=0x0000 +SDRC_CS_CFG_LSB=0x0001 +SDRC_SHARING_LSB=0x0100 +SDRC_ERR_TYPE_LSB=0x0000 +SDRC_DLLA_CTRL=0x0000000A +SDRC_POWER=0x00000081 +MEMORY_TYPE_CS0=0x0003 +SDRC_MCFG_0=0x02D04011 +SDRC_MR_0_LSB=0x0032 +SDRC_EMR1_0_LSB=0x0000 +SDRC_EMR2_0_LSB=0x0000 +SDRC_EMR3_0_LSB=0x0000 +SDRC_ACTIM_CTRLA_0=0xBA9DC4C6 +SDRC_ACTIM_CTRLB_0=0x00012522 +SDRC_RFRCTRL_0=0x0004E201 +MEMORY_TYPE_CS1=0x0003 +SDRC_MCFG_1=0x02D04011 +SDRC_MR_1_LSB=0x0032 +SDRC_EMR1_1_LSB=0x0000 +SDRC_EMR2_1_LSB=0x0000 +SDRC_EMR3_1_LSB=0x0000 +SDRC_ACTIM_CTRLA_1=0xBA9DC4C6 +SDRC_ACTIM_CTRLB_1=0x00012522 +SDRC_RFRCTRL_1=0x0004E201 diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc b/BeagleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc new file mode 100644 index 0000000000..72c0fd75dd --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_boot_from_ram.inc @@ -0,0 +1,21 @@ +// +// 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. +// +error = continue +unload +error = abort + +setreg @CP15_CONTROL = 0x0005107E +setreg @pc=0x80008208 +setreg @cpsr=0x000000D3 +dis/D +readfile,raw,nowarn "ZZZZZZ/FV/BEAGLEBOARD_EFI.fd"=0x80008000 + diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh b/BeagleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh new file mode 100755 index 0000000000..72947cc1c1 --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_convert_symbols.sh @@ -0,0 +1,23 @@ +#!/bin/sh
+#
+# 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.
+#
+
+
+IN=`/usr/bin/cygpath -u $1`
+OUT=`/usr/bin/cygpath -u $2`
+
+/usr/bin/sed -e "s/\/cygdrive\/\(.\)/load\/a\/ni\/np \"\1:/g" \
+ -e 's:\\:/:g' \
+ -e "s/^/load\/a\/ni\/np \"/g" \
+ -e "s/dll /dll\" \&/g" \
+ $IN | /usr/bin/sort.exe --key=3 --output=$OUT
+
diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_dummy.axf b/BeagleBoardPkg/Debugger_scripts/rvi_dummy.axf Binary files differnew file mode 100755 index 0000000000..17fabaa6cc --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_dummy.axf diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_hw_setup.inc b/BeagleBoardPkg/Debugger_scripts/rvi_hw_setup.inc new file mode 100644 index 0000000000..eb5ce57aa3 --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_hw_setup.inc @@ -0,0 +1,67 @@ +// +// 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. +// + +error = continue +unload +error = abort + +setreg @CP15_CONTROL = 0x0005107E +setreg @cpsr=0x000000D3 + +; General clock settings. +setmem /32 0x48307270=0x00000080 +setmem /32 0x48306D40=0x00000003 +setmem /32 0x48005140=0x03020A50 + +;Clock configuration +setmem /32 0x48004A40=0x0000030A +setmem /32 0x48004C40=0x00000015 + +;DPLL3 (Core) settings +setmem /32 0x48004D00=0x00370037 +setmem /32 0x48004D30=0x00000000 +setmem /32 0x48004D40=0x094C0C00 + +;DPLL4 (Peripheral) settings +setmem /32 0x48004D00=0x00370037 +setmem /32 0x48004D30=0x00000000 +setmem /32 0x48004D44=0x0001B00C +setmem /32 0x48004D48=0x00000009 + +;DPLL1 (MPU) settings +setmem /32 0x48004904=0x00000037 +setmem /32 0x48004934=0x00000000 +setmem /32 0x48004940=0x0011F40C +setmem /32 0x48004944=0x00000001 +setmem /32 0x48004948=0x00000000 + +;RAM setup. +setmem /16 0x6D000010=0x0000 +setmem /16 0x6D000040=0x0001 +setmem /16 0x6D000044=0x0100 +setmem /16 0x6D000048=0x0000 +setmem /32 0x6D000060=0x0000000A +setmem /32 0x6D000070=0x00000081 +setmem /16 0x6D000040=0x0003 +setmem /32 0x6D000080=0x02D04011 +setmem /16 0x6D000084=0x0032 +setmem /16 0x6D00008C=0x0000 +setmem /32 0x6D00009C=0xBA9DC4C6 +setmem /32 0x6D0000A0=0x00012522 +setmem /32 0x6D0000A4=0x0004E201 +setmem /16 0x6D000040=0x0003 +setmem /32 0x6D0000B0=0x02D04011 +setmem /16 0x6D0000B4=0x0032 +setmem /16 0x6D0000BC=0x0000 +setmem /32 0x6D0000C4=0xBA9DC4C6 +setmem /32 0x6D0000C8=0x00012522 +setmem /32 0x6D0000D4=0x0004E201
\ No newline at end of file diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_load_symbols.inc b/BeagleBoardPkg/Debugger_scripts/rvi_load_symbols.inc new file mode 100644 index 0000000000..27d4007d1c --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_load_symbols.inc @@ -0,0 +1,23 @@ +//
+// 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 'ZZZZZZ/rvi_symbols_macros.inc'
+
+macro write_symbols_file("ZZZZZZ/rvi_symbols.tmp", 0x00000000, 0x10000000)
+
+host "bash -o igncr ZZZZZZ/rvi_convert_symbols.sh ZZZZZZ/rvi_symbols.tmp ZZZZZZ/rvi_symbols.inc"
+include 'ZZZZZZ/rvi_symbols.inc'
+load /NI /NP 'ZZZZZZ/rvi_dummy.axf' ;.constdata
+unload rvi_dummy.axf
+delfile rvi_dummy.axf
+
+
diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc b/BeagleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc new file mode 100755 index 0000000000..ccd1ea068f --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_symbols_macros.inc @@ -0,0 +1,194 @@ +//
+// Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+//
+// All rights reserved. This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+
+define /R int compare_guid(guid1, guid2)
+ unsigned char *guid1;
+ unsigned char *guid2;
+{
+ return strncmp(guid1, guid2, 16);
+}
+.
+
+define /R unsigned char * find_system_table(mem_start, mem_size)
+ unsigned char *mem_start;
+ unsigned long mem_size;
+{
+ unsigned char *mem_ptr;
+
+ mem_ptr = mem_start + mem_size;
+
+ do
+ {
+ mem_ptr -= 0x400000; // 4 MB
+
+ if (strncmp(mem_ptr, "IBI SYST", 8) == 0)
+ {
+ return *(unsigned long *)(mem_ptr + 8); // EfiSystemTableBase
+ }
+
+ } while (mem_ptr > mem_start);
+
+ return 0;
+}
+.
+
+define /R unsigned char * find_debug_info_table_header(system_table)
+ unsigned char *system_table;
+{
+ unsigned long configuration_table_entries;
+ unsigned char *configuration_table;
+ unsigned long index;
+ unsigned char debug_table_guid[16];
+
+ // Fill in the debug table's guid
+ debug_table_guid[ 0] = 0x77;
+ debug_table_guid[ 1] = 0x2E;
+ debug_table_guid[ 2] = 0x15;
+ debug_table_guid[ 3] = 0x49;
+ debug_table_guid[ 4] = 0xDA;
+ debug_table_guid[ 5] = 0x1A;
+ debug_table_guid[ 6] = 0x64;
+ debug_table_guid[ 7] = 0x47;
+ debug_table_guid[ 8] = 0xB7;
+ debug_table_guid[ 9] = 0xA2;
+ debug_table_guid[10] = 0x7A;
+ debug_table_guid[11] = 0xFE;
+ debug_table_guid[12] = 0xFE;
+ debug_table_guid[13] = 0xD9;
+ debug_table_guid[14] = 0x5E;
+ debug_table_guid[15] = 0x8B;
+
+ configuration_table_entries = *(unsigned long *)(system_table + 64);
+ configuration_table = *(unsigned long *)(system_table + 68);
+
+ for (index = 0; index < configuration_table_entries; index++)
+ {
+ if (compare_guid(configuration_table, debug_table_guid) == 0)
+ {
+ return *(unsigned long *)(configuration_table + 16);
+ }
+
+ configuration_table += 20;
+ }
+
+ return 0;
+}
+.
+
+define /R int valid_pe_header(header)
+ unsigned char *header;
+{
+ if ((header[0x00] == 'M') &&
+ (header[0x01] == 'Z') &&
+ (header[0x80] == 'P') &&
+ (header[0x81] == 'E'))
+ {
+ return 1;
+ }
+
+ return 0;
+}
+.
+
+define /R unsigned long pe_headersize(header)
+ unsigned char *header;
+{
+ unsigned long *size;
+
+ size = header + 0x00AC;
+
+ return *size;
+}
+.
+
+define /R unsigned char *pe_filename(header)
+ unsigned char *header;
+{
+ unsigned long *debugOffset;
+ unsigned char *stringOffset;
+
+ if (valid_pe_header(header))
+ {
+ debugOffset = header + 0x0128;
+ stringOffset = header + *debugOffset + 0x002C;
+
+ return stringOffset;
+ }
+
+ return 0;
+}
+.
+
+define /R int char_is_valid(c)
+ unsigned char c;
+{
+ if (c >= 32 && c < 127)
+ return 1;
+
+ return 0;
+}
+.
+
+define /R write_symbols_file(filename, mem_start, mem_size)
+ unsigned char *filename;
+ unsigned char *mem_start;
+ unsigned long mem_size;
+{
+ unsigned char *system_table;
+ unsigned char *debug_info_table_header;
+ unsigned char *debug_info_table;
+ unsigned long debug_info_table_size;
+ unsigned long index;
+ unsigned char *debug_image_info;
+ unsigned char *loaded_image_protocol;
+ unsigned char *image_base;
+ unsigned char *debug_filename;
+ unsigned long header_size;
+ int status;
+
+ system_table = find_system_table(mem_start, mem_size);
+ if (system_table == 0)
+ {
+ return;
+ }
+
+ status = fopen(88, filename, "w");
+
+ debug_info_table_header = find_debug_info_table_header(system_table);
+
+ debug_info_table = *(unsigned long *)(debug_info_table_header + 8);
+ debug_info_table_size = *(unsigned long *)(debug_info_table_header + 4);
+
+ for (index = 0; index < (debug_info_table_size * 4); index += 4)
+ {
+ debug_image_info = *(unsigned long *)(debug_info_table + index);
+
+ if (debug_image_info == 0)
+ {
+ break;
+ }
+
+ loaded_image_protocol = *(unsigned long *)(debug_image_info + 4);
+
+ image_base = *(unsigned long *)(loaded_image_protocol + 32);
+
+ debug_filename = pe_filename(image_base);
+ header_size = pe_headersize(image_base);
+
+ $fprintf 88, "%s 0x%08x\n", debug_filename, image_base + header_size$;
+ }
+
+
+ fclose(88);
+}
+.
+
diff --git a/BeagleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc b/BeagleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc new file mode 100755 index 0000000000..9d28582fcb --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/rvi_unload_symbols.inc @@ -0,0 +1,118 @@ +//
+// 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.
+//
+
+error = continue
+
+unload
+
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+delfile 1
+
+error = abort
diff --git a/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols.cmm b/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols.cmm new file mode 100644 index 0000000000..0dffaa461a --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols.cmm @@ -0,0 +1,211 @@ +//
+// Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+//
+// All rights reserved. This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+
+ ENTRY &ram_start &ram_size
+
+ ;If system is running then stop the execution so we can load symbols.
+ break
+
+ ;Reset all windows
+ WINPAGE.RESET
+
+ ;Create AREA to display the symbols we are loading.
+ AREA.Reset
+ AREA.Create SYMBOL 300. 100.
+ AREA.View SYMBOL
+ AREA.Select SYMBOL
+ SYS.Option BE OFF
+
+ ;Added based on suggestion from Lauterbach support.
+ MMU.TABLEWALK ON
+ MMU.ON
+
+ ;Load symbols.
+ GOSUB load_symbols &ram_start &ram_size
+
+ ;Open some windows and enable semihosting.
+ TOOLBAR ON
+ STATUSBAR ON
+ WINPAGE.RESET
+
+ WINCLEAR
+ WINPOS 0.0 17.0 72. 13. 0. 0. W000
+ SYStem
+
+ WINPOS 0.0 0.0 110. 55. 13. 1. W001
+ WINTABS 10. 10. 25. 62.
+ Data.List
+
+ WINPAGE.SELECT P000
+
+ //Enable semihosting
+ System.Option.BigEndian OFF
+
+ tronchip.set swi on // ARM9/10/11 variant
+
+ // configure and open semihosting channel
+ winpos 50% 50% 50% 50%
+ term.heapinfo 0 0x20000 0x30000 0x20000
+ term.method armswi
+ term.mode string
+ term.gate
+
+ WINPOS 115.0 0. 70. 35. 0. 1. W002
+ Var.Local %HEX
+
+ WINPOS 115.10 45. 48. 9. 0. 0. W003
+ Register
+
+ END
+
+find_system_table:
+ ENTRY &mem_start &mem_size
+ &mem_ptr=&mem_start+&mem_size
+ RPT
+ (
+ &mem_ptr=&mem_ptr-0x400000 // 4 MB
+ &word1=Data.LONG(D:&mem_ptr)
+ &word2=Data.LONG(D:&mem_ptr+0x04)
+ IF &word1==0x20494249
+ (
+ IF &word2==0x54535953
+ (
+ &result=Data.LONG(D:&mem_ptr+0x08)
+ RETURN &result
+ )
+ )
+ )
+ WHILE &mem_ptr>&mem_start
+ &result=0
+ RETURN &result
+
+compare_guid:
+ ENTRY &guid
+ IF Data.LONG(D:&guid)==0x49152E77
+ (
+ IF Data.LONG(D:&guid+0x04)==0x47641ADA
+ (
+ IF Data.LONG(D:&guid+0x08)==0xFE7AA2B7
+ (
+ IF Data.LONG(D:&guid+0x0C)==0x8B5ED9FE
+ (
+ RETURN 0
+ )
+ )
+ )
+ )
+ RETURN 1
+
+find_debug_info_table_header:
+ ENTRY &system_table
+ &config_table_entries=Data.LONG(D:&system_table+0x40)
+ &config_table_pointer=Data.LONG(D:&system_table+0x44)
+ RPT &config_table_entries
+ (
+ GOSUB compare_guid &config_table_pointer
+ ENTRY &result
+ IF &result==0
+ (
+ &result=Data.LONG(D:&config_table_pointer+0x10)
+ RETURN &result
+ )
+ &config_table_pointer=&config_table_pointer+0x14
+ )
+ RETURN 0;
+
+valid_pe_header:
+ ENTRY &header
+ IF Data.BYTE(D:&header+0x00)==0x4D
+ (
+ IF Data.BYTE(D:&header+0x01)==0x5A
+ (
+ IF Data.BYTE(D:&header+0x80)==0x50
+ (
+ IF Data.BYTE(D:&header+0x81)==0x45
+ (
+ RETURN 1
+ )
+ )
+ )
+ )
+ RETURN 0
+
+get_file_string: + ENTRY &stringOffset + + local &string + + &more_string=data.string(d:&stringOffset) + + if (string.len("&more_string")>=128.) + ( + &string="&string"+"&more_string" + &stringOffset=&stringOffset+string.len("&more_string") + + //Get remaining file string + GOSUB get_file_string &stringOffset + ENTRY &more_string + &string="&string"+"&more_string" + ) + else + ( + &string="&string"+"&more_string" + &more_string="" + )
+ RETURN &string
+
+load_symbol_file:
+ ENTRY &header &load_address
+ GOSUB valid_pe_header &header
+ ENTRY &result
+
+ IF &result==1
+ (
+ &debugOffset=Data.LONG(D:&header+0x0128)
+ &stringOffset=&header+&debugOffset+0x002C
+
+ GOSUB get_file_string &stringOffset
+ ENTRY &filestring
+
+ PRINT "&filestring 0x" &load_address
+ TDIAG Data.load.elf &filestring &load_address /nocode /noclear
+ )
+ RETURN
+
+pe_headersize:
+ ENTRY &header;
+ RETURN Data.LONG(D:&header+0x00AC)
+
+load_symbols:
+ ENTRY &mem_start &mem_size
+ GOSUB find_system_table &mem_start &mem_size
+ ENTRY &system_table
+ GOSUB find_debug_info_table_header &system_table
+ ENTRY &debug_info_table_header
+ &debug_info_table=Data.LONG(D:&debug_info_table_header+0x08)
+ &debug_info_table_size=Data.LONG(D:&debug_info_table_header+0x04)
+ &index=0
+ RPT &debug_info_table_size
+ (
+ &debug_image_info=Data.LONG(D:&debug_info_table+&index)
+ IF &debug_image_info==0
+ RETURN
+ &loaded_image_protocol=Data.LONG(D:&debug_image_info+0x04);
+ &image_base=Data.LONG(D:&loaded_image_protocol+0x20);
+ GOSUB pe_headersize &image_base
+ ENTRY &header_size
+ &image_load_address=&image_base+&header_size
+ GOSUB load_symbol_file &image_base &image_load_address
+ &index=&index+0x4
+ )
+
+ RETURN
diff --git a/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols_cygwin.cmm b/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols_cygwin.cmm new file mode 100644 index 0000000000..011df5254d --- /dev/null +++ b/BeagleBoardPkg/Debugger_scripts/trace32_load_symbols_cygwin.cmm @@ -0,0 +1,188 @@ +//
+// Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+//
+// All rights reserved. This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+
+ ENTRY &ram_start &ram_size
+
+ ;If system is running then stop the execution so we can load symbols.
+ break
+
+ ;Reset all windows
+ WINPAGE.RESET
+
+ AREA.Reset
+ AREA.Create SYMBOL 300. 100.
+ AREA.View SYMBOL
+ AREA.Select SYMBOL
+ SYS.Option BE OFF
+
+ ; Added based on suggestion from Lauterbach support.
+ MMU.TABLEWALK ON
+ MMU.ON
+
+ GOSUB load_symbols &ram_start &ram_size
+
+ ;Open some windows.
+ WINPOS 83.125 29.063 48. 9. 0. 0. W003
+ Register
+
+ WINPOS 83.25 10. 48. 9. 0. 1. W002
+ Var.Local
+
+ END
+
+find_system_table:
+ ENTRY &mem_start &mem_size
+ &mem_ptr=&mem_start+&mem_size
+ RPT
+ (
+ &mem_ptr=&mem_ptr-0x400000 // 4 MB
+ &word1=Data.LONG(D:&mem_ptr)
+ &word2=Data.LONG(D:&mem_ptr+0x04)
+ IF &word1==0x20494249
+ (
+ IF &word2==0x54535953
+ (
+ &result=Data.LONG(D:&mem_ptr+0x08)
+ RETURN &result
+ )
+ )
+ )
+ WHILE &mem_ptr>&mem_start
+ &result=0
+ RETURN &result
+
+compare_guid:
+ ENTRY &guid
+ IF Data.LONG(D:&guid)==0x49152E77
+ (
+ IF Data.LONG(D:&guid+0x04)==0x47641ADA
+ (
+ IF Data.LONG(D:&guid+0x08)==0xFE7AA2B7
+ (
+ IF Data.LONG(D:&guid+0x0C)==0x8B5ED9FE
+ (
+ RETURN 0
+ )
+ )
+ )
+ )
+ RETURN 1
+
+find_debug_info_table_header:
+ ENTRY &system_table
+ &config_table_entries=Data.LONG(D:&system_table+0x40)
+ &config_table_pointer=Data.LONG(D:&system_table+0x44)
+ RPT &config_table_entries
+ (
+ GOSUB compare_guid &config_table_pointer
+ ENTRY &result
+ IF &result==0
+ (
+ &result=Data.LONG(D:&config_table_pointer+0x10)
+ RETURN &result
+ )
+ &config_table_pointer=&config_table_pointer+0x14
+ )
+ RETURN 0;
+
+valid_pe_header:
+ ENTRY &header
+ IF Data.BYTE(D:&header+0x00)==0x4D
+ (
+ IF Data.BYTE(D:&header+0x01)==0x5A
+ (
+ IF Data.BYTE(D:&header+0x80)==0x50
+ (
+ IF Data.BYTE(D:&header+0x81)==0x45
+ (
+ RETURN 1
+ )
+ )
+ )
+ )
+ RETURN 0
+
+get_file_string: + ENTRY &stringOffset + + local &string
+
+ &more_string=data.string(d:&stringOffset) + + if (string.len("&more_string")>=128.) + ( + &string="&string"+"&more_string" + &stringOffset=&stringOffset+string.len("&more_string") + + //Get remaining file string + GOSUB get_file_string &stringOffset + ENTRY &more_string + &string="&string"+"&more_string" + ) + else + ( + &string="&string"+"&more_string" + &more_string="" + )
+ RETURN &string
+
+load_symbol_file:
+ ENTRY &header &load_address
+ GOSUB valid_pe_header &header
+ ENTRY &result
+
+ IF &result==1
+ (
+ &debugOffset=Data.LONG(D:&header+0x0128)
+ &stringOffset=&header+&debugOffset+0x002C
+
+ &stringOffset=&stringOffset+11.
+
+ GOSUB get_file_string &stringOffset
+ ENTRY &filestring
+
+ &filestring="c:"+"&filestring"
+
+ PRINT "&filestring 0x" &load_address
+ Data.load.elf &filestring &load_address /nocode /noclear
+ )
+ RETURN
+
+pe_headersize:
+ ENTRY &header;
+ RETURN Data.LONG(D:&header+0x00AC)
+
+load_symbols:
+ ENTRY &mem_start &mem_size
+ GOSUB find_system_table &mem_start &mem_size
+ ENTRY &system_table
+ GOSUB find_debug_info_table_header &system_table
+ ENTRY &debug_info_table_header
+ &debug_info_table=Data.LONG(D:&debug_info_table_header+0x08)
+ &debug_info_table_size=Data.LONG(D:&debug_info_table_header+0x04)
+ &index=0
+ RPT &debug_info_table_size
+ (
+ &debug_image_info=Data.LONG(D:&debug_info_table+&index)
+ IF &debug_image_info==0
+ RETURN
+ &loaded_image_protocol=Data.LONG(D:&debug_image_info+0x04);
+ &image_base=Data.LONG(D:&loaded_image_protocol+0x20);
+ GOSUB pe_headersize &image_base
+ ENTRY &header_size
+ &image_load_address=&image_base+&header_size
+ GOSUB load_symbol_file &image_base &image_load_address
+ &index=&index+0x4
+ )
+
+ RETURN
+
\ No newline at end of file diff --git a/BeagleBoardPkg/Flash/Flash.c b/BeagleBoardPkg/Flash/Flash.c new file mode 100644 index 0000000000..26a381aa2a --- /dev/null +++ b/BeagleBoardPkg/Flash/Flash.c @@ -0,0 +1,748 @@ +/** @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 "Flash.h" + +NAND_PART_INFO_TABLE gNandPartInfoTable[1] = { + { 0x2C, 0xBA, 17, 11 } +}; + +NAND_FLASH_INFO *gNandFlashInfo = NULL; +UINT8 *gEccCode; +UINTN gNum512BytesChunks = 0; + +//
+// Device path for SemiHosting. It contains our autogened Caller ID GUID.
+//
+typedef struct {
+ VENDOR_DEVICE_PATH Guid;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} FLASH_DEVICE_PATH;
+
+FLASH_DEVICE_PATH gDevicePath = {
+ {
+ { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0 },
+ EFI_CALLER_ID_GUID
+ },
+ { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
+};
+ + +//Actual page address = Column address + Page address + Block address. +UINTN +GetActualPageAddressInBytes ( + UINTN BlockIndex, + UINTN PageIndex +) +{ + //BlockAddressStart = Start of the Block address in actual NAND + //PageAddressStart = Start of the Page address in actual NAND + return ((BlockIndex << gNandFlashInfo->BlockAddressStart) + (PageIndex << gNandFlashInfo->PageAddressStart)); +} + +VOID +NandSendCommand ( + UINT8 Command +) +{ + MmioWrite16(GPMC_NAND_COMMAND_0, Command); +} + +VOID +NandSendAddress ( + UINT8 Address +) +{ + MmioWrite16(GPMC_NAND_ADDRESS_0, Address); +} + +UINT16 +NandReadStatus ( + VOID + ) +{ + //Send READ STATUS command + NandSendCommand(READ_STATUS_CMD); + + //Read status. + return MmioRead16(GPMC_NAND_DATA_0); +} + +VOID +NandSendAddressCycles ( + UINTN Address +) +{ + //Column address + NandSendAddress(Address & 0xff); + Address >>= 8; + + //Column address + NandSendAddress(Address & 0x07); + Address >>= 3; + + //Page and Block address + NandSendAddress(Address & 0xff); + Address >>= 8; + + //Block address + NandSendAddress(Address & 0xff); + Address >>= 8; + + //Block address + NandSendAddress(Address & 0x01); +} + +VOID +GpmcInit ( + VOID + ) +{ + //Enable Smart-idle mode. + MmioWrite32(GPMC_SYSCONFIG, SMARTIDLEMODE); + + //Set IRQSTATUS and IRQENABLE to the reset value + MmioWrite32(GPMC_IRQSTATUS, 0x0); + MmioWrite32(GPMC_IRQENABLE, 0x0); + + //Disable GPMC timeout control. + MmioWrite32(GPMC_TIMEOUT_CONTROL, TIMEOUTDISABLE); + + //Set WRITEPROTECT bit to enable write access. + MmioWrite32(GPMC_CONFIG, WRITEPROTECT_HIGH); + + //NOTE: Following GPMC_CONFIGi_0 register settings are taken from u-boot memory dump. + MmioWrite32(GPMC_CONFIG1_0, DEVICETYPE_NAND | DEVICESIZE_X16); + MmioWrite32(GPMC_CONFIG2_0, CSRDOFFTIME | CSWROFFTIME); + MmioWrite32(GPMC_CONFIG3_0, ADVRDOFFTIME | ADVWROFFTIME); + MmioWrite32(GPMC_CONFIG4_0, OEONTIME | OEOFFTIME | WEONTIME | WEOFFTIME); + MmioWrite32(GPMC_CONFIG5_0, RDCYCLETIME | WRCYCLETIME | RDACCESSTIME | PAGEBURSTACCESSTIME); + MmioWrite32(GPMC_CONFIG6_0, WRACCESSTIME | WRDATAONADMUXBUS | CYCLE2CYCLEDELAY | CYCLE2CYCLESAMECSEN); + MmioWrite32(GPMC_CONFIG7_0, MASKADDRESS_128MB | CSVALID | BASEADDRESS); +} + +EFI_STATUS +NandDetectPart ( + VOID +) +{ + UINT8 NandInfo = 0; + UINT8 PartInfo[5]; + UINTN Index; + BOOLEAN Found = FALSE; + + //Send READ ID command + NandSendCommand(READ_ID_CMD); + + //Send one address cycle. + NandSendAddress(0); + + //Read 5-bytes to idenfity code programmed into the NAND flash devices. + //BYTE 0 = Manufacture ID + //Byte 1 = Device ID + //Byte 2, 3, 4 = Nand part specific information (Page size, Block size etc) + for (Index = 0; Index < sizeof(PartInfo); Index++) { + PartInfo[Index] = MmioRead16(GPMC_NAND_DATA_0); + } + + //Check if the ManufactureId and DeviceId are part of the currently supported nand parts. + for (Index = 0; Index < sizeof(gNandPartInfoTable)/sizeof(NAND_PART_INFO_TABLE); Index++) { + if (gNandPartInfoTable[Index].ManufactureId == PartInfo[0] && gNandPartInfoTable[Index].DeviceId == PartInfo[1]) { + gNandFlashInfo->BlockAddressStart = gNandPartInfoTable[Index].BlockAddressStart; + gNandFlashInfo->PageAddressStart = gNandPartInfoTable[Index].PageAddressStart; + Found = TRUE; + break; + } + } + + if (Found == FALSE) { + DEBUG ((EFI_D_ERROR, "Nand part is not currently supported. Manufacture id: %x, Device id: %x\n", PartInfo[0], PartInfo[1])); + return EFI_NOT_FOUND; + } + + //Populate NAND_FLASH_INFO based on the result of READ ID command. + gNandFlashInfo->ManufactureId = PartInfo[0]; + gNandFlashInfo->DeviceId = PartInfo[1]; + NandInfo = PartInfo[3]; + + if (PAGE_SIZE(NandInfo) == PAGE_SIZE_2K_VAL) { + gNandFlashInfo->PageSize = PAGE_SIZE_2K; + } else { + DEBUG ((EFI_D_ERROR, "Unknown Page size.\n")); + return EFI_DEVICE_ERROR; + } + + if (SPARE_AREA_SIZE(NandInfo) == SPARE_AREA_SIZE_64B_VAL) { + gNandFlashInfo->SparePageSize = SPARE_AREA_SIZE_64B; + } else { + DEBUG ((EFI_D_ERROR, "Unknown Spare area size.\n")); + return EFI_DEVICE_ERROR; + } + + if (BLOCK_SIZE(NandInfo) == BLOCK_SIZE_128K_VAL) { + gNandFlashInfo->BlockSize = BLOCK_SIZE_128K; + } else { + DEBUG ((EFI_D_ERROR, "Unknown Block size.\n")); + return EFI_DEVICE_ERROR; + } + + if (ORGANIZATION(NandInfo) == ORGANIZATION_X8) { + gNandFlashInfo->Organization = 0; + } else if (ORGANIZATION(NandInfo) == ORGANIZATION_X16) { + gNandFlashInfo->Organization = 1; + } + + //Calculate total number of blocks. + gNandFlashInfo->NumPagesPerBlock = DivU64x32(gNandFlashInfo->BlockSize, gNandFlashInfo->PageSize); + + return EFI_SUCCESS; +} + +VOID +NandConfigureEcc ( + VOID + ) +{ + //Define ECC size 0 and size 1 to 512 bytes + MmioWrite32(GPMC_ECC_SIZE_CONFIG, (ECCSIZE0_512BYTES | ECCSIZE1_512BYTES)); +} + +VOID +NandEnableEcc ( + VOID + ) +{ + //Clear all the ECC result registers and select ECC result register 1 + MmioWrite32(GPMC_ECC_CONTROL, (ECCCLEAR | ECCPOINTER_REG1)); + + //Enable ECC engine on CS0 + MmioWrite32(GPMC_ECC_CONFIG, (ECCENABLE | ECCCS_0 | ECC16B)); +} + +VOID +NandDisableEcc ( + VOID + ) +{ + //Turn off ECC engine. + MmioWrite32(GPMC_ECC_CONFIG, ECCDISABLE); +} + +VOID +NandCalculateEcc ( + VOID + ) +{ + UINTN Index; + UINTN EccResultRegister; + UINTN EccResult; + + //Capture 32-bit ECC result for each 512-bytes chunk. + //In our case PageSize is 2K so read ECC1-ECC4 result registers and + //generate total of 12-bytes of ECC code for the particular page. + + EccResultRegister = GPMC_ECC1_RESULT; + + for (Index = 0; Index < gNum512BytesChunks; Index++) { + + EccResult = MmioRead32(EccResultRegister); + + //Calculate ECC code from 32-bit ECC result value. + //NOTE: Following calculation is not part of TRM. We got this information + //from Beagleboard mailing list. + gEccCode[Index * 3] = EccResult & 0xFF; + gEccCode[(Index * 3) + 1] = (EccResult >> 16) & 0xFF; + gEccCode[(Index * 3) + 2] = (((EccResult >> 20) & 0xF0) | ((EccResult >> 8) & 0x0F)); + + //Point to next ECC result register. + EccResultRegister += 4; + } +} + +EFI_STATUS +NandReadPage ( + IN UINTN BlockIndex, + IN UINTN PageIndex, + OUT VOID *Buffer, + OUT UINT8 *SpareBuffer +) +{ + UINTN Address; + UINTN Index; + UINTN NumMainAreaWords = (gNandFlashInfo->PageSize/2); + UINTN NumSpareAreaWords = (gNandFlashInfo->SparePageSize/2); + UINT16 *MainAreaWordBuffer = Buffer; + UINT16 *SpareAreaWordBuffer = (UINT16 *)SpareBuffer; + UINTN Timeout = MAX_RETRY_COUNT; + + //Generate device address in bytes to access specific block and page index + Address = GetActualPageAddressInBytes(BlockIndex, PageIndex); + + //Send READ command + NandSendCommand(PAGE_READ_CMD); + + //Send 5 Address cycles to access specific device address + NandSendAddressCycles(Address); + + //Send READ CONFIRM command + NandSendCommand(PAGE_READ_CONFIRM_CMD); + + //Poll till device is busy. + while (Timeout) { + if ((NandReadStatus() & NAND_READY) == NAND_READY) { + break; + } + Timeout--; + } + + if (Timeout == 0) { + DEBUG ((EFI_D_ERROR, "Read page timed out.\n")); + return EFI_TIMEOUT; + } + + //Reissue READ command + NandSendCommand(PAGE_READ_CMD); + + //Enable ECC engine. + NandEnableEcc(); + + //Read data into the buffer. + for (Index = 0; Index < NumMainAreaWords; Index++) { + *MainAreaWordBuffer++ = MmioRead16(GPMC_NAND_DATA_0); + } + + //Read spare area into the buffer. + for (Index = 0; Index < NumSpareAreaWords; Index++) { + *SpareAreaWordBuffer++ = MmioRead16(GPMC_NAND_DATA_0); + } + + //Calculate ECC. + NandCalculateEcc(); + + //Turn off ECC engine. + NandDisableEcc(); + + //Perform ECC correction. + //Need to implement.. + + return EFI_SUCCESS; +} + +EFI_STATUS +NandWritePage ( + IN UINTN BlockIndex, + IN UINTN PageIndex, + OUT VOID *Buffer, + IN UINT8 *SpareBuffer +) +{ + UINTN Address; + UINT16 *MainAreaWordBuffer = Buffer; + UINT16 *SpareAreaWordBuffer = (UINT16 *)SpareBuffer; + UINTN Index; + UINTN NandStatus; + UINTN Timeout = MAX_RETRY_COUNT; + + //Generate device address in bytes to access specific block and page index + Address = GetActualPageAddressInBytes(BlockIndex, PageIndex); + + //Send SERIAL DATA INPUT command + NandSendCommand(PROGRAM_PAGE_CMD); + + //Send 5 Address cycles to access specific device address + NandSendAddressCycles(Address); + + //Enable ECC engine. + NandEnableEcc(); + + //Data input from Buffer + for (Index = 0; Index < (gNandFlashInfo->PageSize/2); Index++) { + MmioWrite16(GPMC_NAND_DATA_0, *MainAreaWordBuffer++); + + //After each write access, device has to wait to accept data. + //Currently we may not be programming proper timing parameters to + //the GPMC_CONFIGi_0 registers and we would need to figure that out. + //Without following delay, page programming fails. + gBS->Stall(1); + } + + //Calculate ECC. + NandCalculateEcc(); + + //Turn off ECC engine. + NandDisableEcc(); + + //Prepare Spare area buffer with ECC codes. + SetMem(SpareBuffer, gNandFlashInfo->SparePageSize, 0xFF); + CopyMem(&SpareBuffer[ECC_POSITION], gEccCode, gNum512BytesChunks * 3); + + //Program spare area with calculated ECC. + for (Index = 0; Index < (gNandFlashInfo->SparePageSize/2); Index++) { + MmioWrite16(GPMC_NAND_DATA_0, *SpareAreaWordBuffer++); + } + + //Send PROGRAM command + NandSendCommand(PROGRAM_PAGE_CONFIRM_CMD); + + //Poll till device is busy. + while (Timeout) { + NandStatus = NandReadStatus(); + if ((NandStatus & NAND_READY) == NAND_READY) { + break; + } + Timeout--; + } + + if (Timeout == 0) { + DEBUG ((EFI_D_ERROR, "Program page timed out.\n")); + return EFI_TIMEOUT; + } + + //Bit0 indicates Pass/Fail status + if (NandStatus & NAND_FAILURE) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +NandEraseBlock ( + IN UINTN BlockIndex +) +{ + UINTN Address; + UINTN NandStatus; + UINTN Timeout = MAX_RETRY_COUNT; + + //Generate device address in bytes to access specific block and page index + Address = GetActualPageAddressInBytes(BlockIndex, 0); + + //Send ERASE SETUP command + NandSendCommand(BLOCK_ERASE_CMD); + + //Send 3 address cycles to device to access Page address and Block address + Address >>= 11; //Ignore column addresses + + NandSendAddress(Address & 0xff); + Address >>= 8; + + NandSendAddress(Address & 0xff); + Address >>= 8; + + NandSendAddress(Address & 0xff); + + //Send ERASE CONFIRM command + NandSendCommand(BLOCK_ERASE_CONFIRM_CMD); + + //Poll till device is busy. + while (Timeout) { + NandStatus = NandReadStatus(); + if ((NandStatus & NAND_READY) == NAND_READY) { + break; + } + Timeout--; + gBS->Stall(1); + } + + if (Timeout == 0) { + DEBUG ((EFI_D_ERROR, "Erase block timed out for Block: %d.\n", BlockIndex)); + return EFI_TIMEOUT; + } + + //Bit0 indicates Pass/Fail status + if (NandStatus & NAND_FAILURE) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +NandReadBlock ( + IN UINTN StartBlockIndex, + IN UINTN EndBlockIndex, + OUT VOID *Buffer, + OUT VOID *SpareBuffer +) +{ + UINTN BlockIndex; + UINTN PageIndex; + EFI_STATUS Status = EFI_SUCCESS; + + for (BlockIndex = StartBlockIndex; BlockIndex <= EndBlockIndex; BlockIndex++) { + //For each block read number of pages + for (PageIndex = 0; PageIndex < gNandFlashInfo->NumPagesPerBlock; PageIndex++) { + Status = NandReadPage(BlockIndex, PageIndex, Buffer, SpareBuffer); + if (EFI_ERROR(Status)) { + return Status; + } + Buffer = ((UINT8 *)Buffer + gNandFlashInfo->PageSize); + } + } + + return Status; +} + +EFI_STATUS +NandWriteBlock ( + IN UINTN StartBlockIndex, + IN UINTN EndBlockIndex, + OUT VOID *Buffer, + OUT VOID *SpareBuffer + ) +{ + UINTN BlockIndex; + UINTN PageIndex; + EFI_STATUS Status = EFI_SUCCESS; + + for (BlockIndex = StartBlockIndex; BlockIndex <= EndBlockIndex; BlockIndex++) { + //Page programming. + for (PageIndex = 0; PageIndex < gNandFlashInfo->NumPagesPerBlock; PageIndex++) { + Status = NandWritePage(BlockIndex, PageIndex, Buffer, SpareBuffer); + if (EFI_ERROR(Status)) { + return Status; + } + Buffer = ((UINT8 *)Buffer + gNandFlashInfo->PageSize); + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +NandFlashReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + UINTN BusyStall = 50; // microSeconds + UINTN ResetBusyTimeout = (1000000 / BusyStall); // 1 Second + + //Send RESET command to device. + NandSendCommand(RESET_CMD); + + //Wait for 1ms before we check status register. + gBS->Stall(1000); + + //Check BIT#5 & BIT#6 in Status register to make sure RESET is done. + while ((NandReadStatus() & NAND_RESET_STATUS) != NAND_RESET_STATUS) { + + //In case of extended verification, wait for extended amount of time + //to make sure device is reset. + if (ExtendedVerification) { + if (ResetBusyTimeout == 0) { + return EFI_DEVICE_ERROR; + } + + gBS->Stall(BusyStall); + ResetBusyTimeout--; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +NandFlashReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + UINTN NumBlocks; + UINTN EndBlockIndex; + EFI_STATUS Status; + UINT8 *SpareBuffer = NULL; + + if (Buffer == NULL) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (Lba > LAST_BLOCK) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if ((BufferSize % gNandFlashInfo->BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + goto exit; + } + + NumBlocks = DivU64x32(BufferSize, gNandFlashInfo->BlockSize); + EndBlockIndex = ((UINTN)Lba + NumBlocks) - 1; + + SpareBuffer = (UINT8 *)AllocatePool(gNandFlashInfo->SparePageSize); + if (SpareBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + //Read block + Status = NandReadBlock((UINTN)Lba, EndBlockIndex, Buffer, SpareBuffer); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Read block fails: %x\n", Status)); + goto exit; + } + +exit: + if (SpareBuffer != NULL) { + FreePool (SpareBuffer); + } + + return Status; +} + +EFI_STATUS +EFIAPI +NandFlashWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + UINTN BlockIndex; + UINTN NumBlocks; + UINTN EndBlockIndex; + EFI_STATUS Status; + UINT8 *SpareBuffer = NULL; + + if (Buffer == NULL) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if (Lba > LAST_BLOCK) { + Status = EFI_INVALID_PARAMETER; + goto exit; + } + + if ((BufferSize % gNandFlashInfo->BlockSize) != 0) { + Status = EFI_BAD_BUFFER_SIZE; + goto exit; + } + + NumBlocks = DivU64x32(BufferSize, gNandFlashInfo->BlockSize); + EndBlockIndex = ((UINTN)Lba + NumBlocks) - 1; + + SpareBuffer = (UINT8 *)AllocatePool(gNandFlashInfo->SparePageSize); + if (SpareBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + // Erase block + for (BlockIndex = (UINTN)Lba; BlockIndex <= EndBlockIndex; BlockIndex++) { + Status = NandEraseBlock(BlockIndex); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Erase block failed. Status: %x\n", Status)); + goto exit; + } + } + + // Program data + Status = NandWriteBlock((UINTN)Lba, EndBlockIndex, Buffer, SpareBuffer); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Block write fails: %x\n", Status)); + goto exit; + } + +exit: + if (SpareBuffer != NULL) { + FreePool (SpareBuffer); + } + + return Status; +} + +EFI_STATUS +EFIAPI +NandFlashFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +EFI_BLOCK_IO_PROTOCOL BlockIo = +{ + EFI_BLOCK_IO_INTERFACE_REVISION, // Revision + &NandFlashMedia, // *Media + NandFlashReset, // Reset + NandFlashReadBlocks, // ReadBlocks + NandFlashWriteBlocks, // WriteBlocks + NandFlashFlushBlocks // FlushBlocks +}; + +EFI_STATUS +NandFlashInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + gNandFlashInfo = (NAND_FLASH_INFO *)AllocateZeroPool(sizeof(NAND_FLASH_INFO)); + + //Initialize GPMC module. + GpmcInit(); + + //Reset NAND part + NandFlashReset(&BlockIo, FALSE); + + //Detect NAND part and populate gNandFlashInfo structure + Status = NandDetectPart(); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "Nand part id detection failure: Status: %x\n", Status)); + return Status; + } + + //Count total number of 512Bytes chunk based on the page size. + if (gNandFlashInfo->PageSize == PAGE_SIZE_512B) { + gNum512BytesChunks = 1; + } else if (gNandFlashInfo->PageSize == PAGE_SIZE_2K) { + gNum512BytesChunks = 4; + } else if (gNandFlashInfo->PageSize == PAGE_SIZE_4K) { + gNum512BytesChunks = 8; + } + + gEccCode = (UINT8 *)AllocatePool(gNum512BytesChunks * 3); + if (gEccCode == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + //Configure ECC + NandConfigureEcc(); + + //Patch EFI_BLOCK_IO_MEDIA structure. + NandFlashMedia.BlockSize = gNandFlashInfo->BlockSize; + NandFlashMedia.LastBlock = LAST_BLOCK; + + //Publish BlockIO. + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiBlockIoProtocolGuid, &BlockIo, + &gEfiDevicePathProtocolGuid, &gDevicePath, + NULL + ); + return Status; +} + diff --git a/BeagleBoardPkg/Flash/Flash.h b/BeagleBoardPkg/Flash/Flash.h new file mode 100644 index 0000000000..533e416c7e --- /dev/null +++ b/BeagleBoardPkg/Flash/Flash.h @@ -0,0 +1,118 @@ +/** @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 FLASH_H +#define FLASH_H + +#include <Uefi.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/IoLib.h> + +#include <Protocol/BlockIo.h> +#include <Protocol/Cpu.h> +#include <Omap3530/Omap3530.h> + +#define PAGE_SIZE(x) ((x) & 0x01) +#define PAGE_SIZE_2K_VAL (0x01UL) + +#define SPARE_AREA_SIZE(x) (((x) >> 2) & 0x01) +#define SPARE_AREA_SIZE_64B_VAL (0x1UL) + +#define BLOCK_SIZE(x) (((x) >> 4) & 0x01) +#define BLOCK_SIZE_128K_VAL (0x01UL) + +#define ORGANIZATION(x) (((x) >> 6) & 0x01) +#define ORGANIZATION_X8 (0x0UL) +#define ORGANIZATION_X16 (0x1UL) + +#define PAGE_SIZE_512B (512) +#define PAGE_SIZE_2K (2048) +#define PAGE_SIZE_4K (4096) +#define SPARE_AREA_SIZE_16B (16) +#define SPARE_AREA_SIZE_64B (64) + +#define BLOCK_SIZE_16K (16*1024) +#define BLOCK_SIZE_128K (128*1024) + +#define BLOCK_COUNT (2048) +#define LAST_BLOCK (BLOCK_COUNT - 1) + +#define ECC_POSITION 2 + +//List of commands. +#define RESET_CMD 0xFF +#define READ_ID_CMD 0x90 + +#define READ_STATUS_CMD 0x70 + +#define PAGE_READ_CMD 0x00 +#define PAGE_READ_CONFIRM_CMD 0x30 + +#define BLOCK_ERASE_CMD 0x60 +#define BLOCK_ERASE_CONFIRM_CMD 0xD0 + +#define PROGRAM_PAGE_CMD 0x80 +#define PROGRAM_PAGE_CONFIRM_CMD 0x10 + +//Nand status register bit definition +#define NAND_SUCCESS (0x0UL << 0) +#define NAND_FAILURE (0x1UL << 0) + +#define NAND_BUSY (0x0UL << 6) +#define NAND_READY (0x1UL << 6) + +#define NAND_RESET_STATUS (0x60UL << 0) + +#define MAX_RETRY_COUNT 1500 + +EFI_BLOCK_IO_MEDIA NandFlashMedia = { + SIGNATURE_32('n','a','n','d'), // MediaId + FALSE, // RemovableMedia + TRUE, // MediaPresent + TRUE, // LogicalPartition + FALSE, // ReadOnly + FALSE, // WriteCaching + 0, // BlockSize + 2, // IoAlign + 0, // Pad + 0 // LastBlock +}; + +typedef struct { + UINT8 ManufactureId; + UINT8 DeviceId; + UINT8 BlockAddressStart; //Start of the Block address in actual NAND + UINT8 PageAddressStart; //Start of the Page address in actual NAND +} NAND_PART_INFO_TABLE; + +typedef struct { + UINT8 ManufactureId; + UINT8 DeviceId; + UINT8 Organization; //x8 or x16 + UINT32 PageSize; + UINT32 SparePageSize; + UINT32 BlockSize; + UINT32 NumPagesPerBlock; + UINT8 BlockAddressStart; //Start of the Block address in actual NAND + UINT8 PageAddressStart; //Start of the Page address in actual NAND +} NAND_FLASH_INFO; + +#endif //FLASH_H diff --git a/BeagleBoardPkg/Flash/Flash.inf b/BeagleBoardPkg/Flash/Flash.inf new file mode 100644 index 0000000000..bb089850e1 --- /dev/null +++ b/BeagleBoardPkg/Flash/Flash.inf @@ -0,0 +1,36 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = NandFlash + FILE_GUID = 4d00ef14-c4e0-426b-81b7-30a00a14aad6 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = NandFlashInitialize + + +[Sources.common] + Flash.c + +[Packages] + MdePkg/MdePkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + IoLib + +[Guids] + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiCpuArchProtocolGuid + +[Pcd] + gBeagleBoardTokenSpaceGuid.PcdBeagleGpmcOffset + +[depex] + TRUE
\ No newline at end of file diff --git a/BeagleBoardPkg/Gpio/Gpio.c b/BeagleBoardPkg/Gpio/Gpio.c new file mode 100644 index 0000000000..7bc5478933 --- /dev/null +++ b/BeagleBoardPkg/Gpio/Gpio.c @@ -0,0 +1,135 @@ +/** @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/IoLib.h> +#include <Library/OmapLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/EmbeddedGpio.h> + +#include <Omap3530/Omap3530.h> + +EFI_STATUS +Get ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT UINTN *Value + ) +{ + UINTN Port; + UINTN Pin; + UINT32 DataInRegister; + + if (Value == NULL) + { + return EFI_UNSUPPORTED; + } + + Port = GPIO_PORT(Gpio); + Pin = GPIO_PIN(Gpio); + + DataInRegister = GpioBase(Port) + GPIO_DATAIN; + + if (MmioRead32(DataInRegister) & GPIO_DATAIN_MASK(Pin)) { + *Value = 1; + } else { + *Value = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +Set ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_MODE Mode + ) +{ + UINTN Port; + UINTN Pin; + UINT32 OutputEnableRegister; + UINT32 SetDataOutRegister; + UINT32 ClearDataOutRegister; + + Port = GPIO_PORT(Gpio); + Pin = GPIO_PIN(Gpio); + + OutputEnableRegister = GpioBase(Port) + GPIO_OE; + SetDataOutRegister = GpioBase(Port) + GPIO_SETDATAOUT; + ClearDataOutRegister = GpioBase(Port) + GPIO_CLEARDATAOUT; + + switch (Mode) + { + case GPIO_MODE_INPUT: + MmioAndThenOr32(OutputEnableRegister, ~GPIO_OE_MASK(Pin), GPIO_OE_INPUT(Pin)); + break; + + case GPIO_MODE_OUTPUT_0: + MmioWrite32(ClearDataOutRegister, GPIO_CLEARDATAOUT_BIT(Pin)); + MmioAndThenOr32(OutputEnableRegister, ~GPIO_OE_MASK(Pin), GPIO_OE_OUTPUT(Pin)); + break; + + case GPIO_MODE_OUTPUT_1: + MmioWrite32(SetDataOutRegister, GPIO_SETDATAOUT_BIT(Pin)); + MmioAndThenOr32(OutputEnableRegister, ~GPIO_OE_MASK(Pin), GPIO_OE_OUTPUT(Pin)); + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetMode ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT EMBEDDED_GPIO_MODE *Mode + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +SetPull ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_PULL Direction + ) +{ + return EFI_UNSUPPORTED; +} + +EMBEDDED_GPIO Gpio = { + Get, + Set, + GetMode, + SetPull +}; + +EFI_STATUS +GpioInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, &gEmbeddedGpioProtocolGuid, &Gpio, NULL); + return Status; +} diff --git a/BeagleBoardPkg/Gpio/Gpio.inf b/BeagleBoardPkg/Gpio/Gpio.inf new file mode 100644 index 0000000000..c903ed9052 --- /dev/null +++ b/BeagleBoardPkg/Gpio/Gpio.inf @@ -0,0 +1,33 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Gpio + FILE_GUID = E7D9CAE1-6930-46E3-BDF9-0027446E7DF2 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = GpioInitialize + + +[Sources.common] + Gpio.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + IoLib + UefiDriverEntryPoint + OmapLib + +[Guids] + +[Protocols] + gEmbeddedGpioProtocolGuid + +[Pcd] + +[depex] + TRUE
\ No newline at end of file diff --git a/BeagleBoardPkg/Include/Library/BeagleBoardSystemLib.h b/BeagleBoardPkg/Include/Library/BeagleBoardSystemLib.h new file mode 100644 index 0000000000..93a6113262 --- /dev/null +++ b/BeagleBoardPkg/Include/Library/BeagleBoardSystemLib.h @@ -0,0 +1,36 @@ +/** @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 __BEAGLEBOARD_YSTEMLIB_H__ +#define __BEAGLEBOARD_YSTEMLIB_H__ + +VOID +EFIAPI +GoLittleEndian ( + UINTN ImageAddress + ); + +VOID +EFIAPI +ResetSystem ( + IN EFI_RESET_TYPE ResetType + ); + +VOID +EFIAPI +ShutdownEfi ( + VOID + ); + +#endif // __BEAGLEBOARD_YSTEMLIB_H__ diff --git a/BeagleBoardPkg/Include/Library/OmapLib.h b/BeagleBoardPkg/Include/Library/OmapLib.h new file mode 100644 index 0000000000..e2845ca7df --- /dev/null +++ b/BeagleBoardPkg/Include/Library/OmapLib.h @@ -0,0 +1,39 @@ +/** @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 __OMAPLIB_H__ +#define __OMAPLIB_H__ + +UINT32 +GpioBase ( + IN UINTN Port + ); + +UINT32 +TimerBase ( + IN UINTN Timer + ); + +UINTN +InterruptVectorForTimer ( + IN UINTN TImer + ); + +UINT32 +UartBase ( + IN UINTN Uart + ); + +#endif // __OMAPLIB_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530.h b/BeagleBoardPkg/Include/Omap3530/Omap3530.h new file mode 100644 index 0000000000..7d3b011327 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530.h @@ -0,0 +1,38 @@ +/** @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 __OMAP3530_H__ +#define __OMAP3530_H__ + +#include "Omap3530Gpio.h" +#include "Omap3530Interrupt.h" +#include "Omap3530Prcm.h" +#include "Omap3530Timer.h" +#include "Omap3530Uart.h" +#include "Omap3530Usb.h" +#include "Omap3530MMCHS.h" +#include "Omap3530I2c.h" +#include "Omap3530PadConfiguration.h" +#include "Omap3530Gpmc.h" + +//CONTROL_PBIAS_LITE +#define CONTROL_PBIAS_LITE 0x48002520 +#define PBIASLITEVMODE0 (0x1UL << 0) +#define PBIASLITEPWRDNZ0 (0x1UL << 1) +#define PBIASSPEEDCTRL0 (0x1UL << 2) +#define PBIASLITEVMODE1 (0x1UL << 8) +#define PBIASLITEWRDNZ1 (0x1UL << 9) + +#endif // __OMAP3530_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Gpio.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Gpio.h new file mode 100644 index 0000000000..6e825a725c --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Gpio.h @@ -0,0 +1,131 @@ +/** @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 __OMAP3530GPIO_H__ +#define __OMAP3530GPIO_H__ + +#define GPIO1_BASE (0x48310000) +#define GPIO2_BASE (0x49050000) +#define GPIO3_BASE (0x49052000) +#define GPIO4_BASE (0x49054000) +#define GPIO5_BASE (0x49056000) +#define GPIO6_BASE (0x49058000) + +#define GPIO_SYSCONFIG (0x0010) +#define GPIO_SYSSTATUS (0x0014) +#define GPIO_IRQSTATUS1 (0x0018) +#define GPIO_IRQENABLE1 (0x001C) +#define GPIO_WAKEUPENABLE (0x0020) +#define GPIO_IRQSTATUS2 (0x0028) +#define GPIO_IRQENABLE2 (0x002C) +#define GPIO_CTRL (0x0030) +#define GPIO_OE (0x0034) +#define GPIO_DATAIN (0x0038) +#define GPIO_DATAOUT (0x003C) +#define GPIO_LEVELDETECT0 (0x0040) +#define GPIO_LEVELDETECT1 (0x0044) +#define GPIO_RISINGDETECT (0x0048) +#define GPIO_FALLINGDETECT (0x004C) +#define GPIO_DEBOUNCENABLE (0x0050) +#define GPIO_DEBOUNCINGTIME (0x0054) +#define GPIO_CLEARIRQENABLE1 (0x0060) +#define GPIO_SETIRQENABLE1 (0x0064) +#define GPIO_CLEARIRQENABLE2 (0x0070) +#define GPIO_SETIRQENABLE2 (0x0074) +#define GPIO_CLEARWKUENA (0x0080) +#define GPIO_SETWKUENA (0x0084) +#define GPIO_CLEARDATAOUT (0x0090) +#define GPIO_SETDATAOUT (0x0094) + +#define GPIO_SYSCONFIG_IDLEMODE_MASK (3UL << 3) +#define GPIO_SYSCONFIG_IDLEMODE_FORCE (0UL << 3) +#define GPIO_SYSCONFIG_IDLEMODE_NONE (1UL << 3) +#define GPIO_SYSCONFIG_IDLEMODE_SMART (2UL << 3) +#define GPIO_SYSCONFIG_ENAWAKEUP_MASK (1UL << 2) +#define GPIO_SYSCONFIG_ENAWAKEUP_DISABLE (0UL << 2) +#define GPIO_SYSCONFIG_ENAWAKEUP_ENABLE (1UL << 2) +#define GPIO_SYSCONFIG_SOFTRESET_MASK (1UL << 1) +#define GPIO_SYSCONFIG_SOFTRESET_NORMAL (0UL << 1) +#define GPIO_SYSCONFIG_SOFTRESET_RESET (1UL << 1) +#define GPIO_SYSCONFIG_AUTOIDLE_MASK (1UL << 0) +#define GPIO_SYSCONFIG_AUTOIDLE_FREE_RUN (0UL << 0) +#define GPIO_SYSCONFIG_AUTOIDLE_ON (1UL << 0) + +#define GPIO_SYSSTATUS_RESETDONE_MASK (1UL << 0) +#define GPIO_SYSSTATUS_RESETDONE_ONGOING (0UL << 0) +#define GPIO_SYSSTATUS_RESETDONE_COMPLETE (1UL << 0) + +#define GPIO_IRQSTATUS_MASK(x) (1UL << (x)) +#define GPIO_IRQSTATUS_NOT_TRIGGERED(x) (0UL << (x)) +#define GPIO_IRQSTATUS_TRIGGERED(x) (1UL << (x)) +#define GPIO_IRQSTATUS_CLEAR(x) (1UL << (x)) + +#define GPIO_IRQENABLE_MASK(x) (1UL << (x)) +#define GPIO_IRQENABLE_DISABLE(x) (0UL << (x)) +#define GPIO_IRQENABLE_ENABLE(x) (1UL << (x)) + +#define GPIO_WAKEUPENABLE_MASK(x) (1UL << (x)) +#define GPIO_WAKEUPENABLE_DISABLE(x) (0UL << (x)) +#define GPIO_WAKEUPENABLE_ENABLE(x) (1UL << (x)) + +#define GPIO_CTRL_GATINGRATIO_MASK (3UL << 1) +#define GPIO_CTRL_GATINGRATIO_DIV_1 (0UL << 1) +#define GPIO_CTRL_GATINGRATIO_DIV_2 (1UL << 1) +#define GPIO_CTRL_GATINGRATIO_DIV_4 (2UL << 1) +#define GPIO_CTRL_GATINGRATIO_DIV_8 (3UL << 1) +#define GPIO_CTRL_DISABLEMODULE_MASK (1UL << 0) +#define GPIO_CTRL_DISABLEMODULE_ENABLE (0UL << 0) +#define GPIO_CTRL_DISABLEMODULE_DISABLE (1UL << 0) + +#define GPIO_OE_MASK(x) (1UL << (x)) +#define GPIO_OE_OUTPUT(x) (0UL << (x)) +#define GPIO_OE_INPUT(x) (1UL << (x)) + +#define GPIO_DATAIN_MASK(x) (1UL << (x)) + +#define GPIO_DATAOUT_MASK(x) (1UL << (x)) + +#define GPIO_LEVELDETECT_MASK(x) (1UL << (x)) +#define GPIO_LEVELDETECT_DISABLE(x) (0UL << (x)) +#define GPIO_LEVELDETECT_ENABLE(x) (1UL << (x)) + +#define GPIO_RISINGDETECT_MASK(x) (1UL << (x)) +#define GPIO_RISINGDETECT_DISABLE(x) (0UL << (x)) +#define GPIO_RISINGDETECT_ENABLE(x) (1UL << (x)) + +#define GPIO_FALLINGDETECT_MASK(x) (1UL << (x)) +#define GPIO_FALLINGDETECT_DISABLE(x) (0UL << (x)) +#define GPIO_FALLINGDETECT_ENABLE(x) (1UL << (x)) + +#define GPIO_DEBOUNCENABLE_MASK(x) (1UL << (x)) +#define GPIO_DEBOUNCENABLE_DISABLE(x) (0UL << (x)) +#define GPIO_DEBOUNCENABLE_ENABLE(x) (1UL << (x)) + +#define GPIO_DEBOUNCINGTIME_MASK (0xFF) +#define GPIO_DEBOUNCINGTIME_US(x) ((((x) / 31) - 1) & GPIO_DEBOUNCINGTIME_MASK) + +#define GPIO_CLEARIRQENABLE_BIT(x) (1UL << (x)) + +#define GPIO_SETIRQENABLE_BIT(x) (1UL << (x)) + +#define GPIO_CLEARWKUENA_BIT(x) (1UL << (x)) + +#define GPIO_SETWKUENA_BIT(x) (1UL << (x)) + +#define GPIO_CLEARDATAOUT_BIT(x) (1UL << (x)) + +#define GPIO_SETDATAOUT_BIT(x) (1UL << (x)) + +#endif // __OMAP3530GPIO_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Gpmc.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Gpmc.h new file mode 100644 index 0000000000..907806c378 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Gpmc.h @@ -0,0 +1,107 @@ +/** @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 __OMAP3530GPMC_H__ +#define __OMAP3530GPMC_H__ + +#define GPMC_BASE (0x6E000000) + +//GPMC NAND definitions. +#define GPMC_SYSCONFIG (GPMC_BASE + 0x10) +#define SMARTIDLEMODE (0x2UL << 3) + +#define GPMC_SYSSTATUS (GPMC_BASE + 0x14) +#define GPMC_IRQSTATUS (GPMC_BASE + 0x18) +#define GPMC_IRQENABLE (GPMC_BASE + 0x1C) + +#define GPMC_TIMEOUT_CONTROL (GPMC_BASE + 0x40) +#define TIMEOUTENABLE (0x1UL << 0) +#define TIMEOUTDISABLE (0x0UL << 0) + +#define GPMC_ERR_ADDRESS (GPMC_BASE + 0x44) +#define GPMC_ERR_TYPE (GPMC_BASE + 0x48) + +#define GPMC_CONFIG (GPMC_BASE + 0x50) +#define WRITEPROTECT_HIGH (0x1UL << 4) +#define WRITEPROTECT_LOW (0x0UL << 4) + +#define GPMC_STATUS (GPMC_BASE + 0x54) + +#define GPMC_CONFIG1_0 (GPMC_BASE + 0x60) +#define DEVICETYPE_NOR (0x0UL << 10) +#define DEVICETYPE_NAND (0x2UL << 10) +#define DEVICESIZE_X8 (0x0UL << 12) +#define DEVICESIZE_X16 (0x1UL << 12) + +#define GPMC_CONFIG2_0 (GPMC_BASE + 0x64) +#define CSONTIME (0x0UL << 0) +#define CSRDOFFTIME (0x14UL << 8) +#define CSWROFFTIME (0x14UL << 16) + +#define GPMC_CONFIG3_0 (GPMC_BASE + 0x68) +#define ADVRDOFFTIME (0x14UL << 8) +#define ADVWROFFTIME (0x14UL << 16) + +#define GPMC_CONFIG4_0 (GPMC_BASE + 0x6C) +#define OEONTIME (0x1UL << 0) +#define OEOFFTIME (0xFUL << 8) +#define WEONTIME (0x1UL << 16) +#define WEOFFTIME (0xFUL << 24) + +#define GPMC_CONFIG5_0 (GPMC_BASE + 0x70) +#define RDCYCLETIME (0x14UL << 0) +#define WRCYCLETIME (0x14UL << 8) +#define RDACCESSTIME (0xCUL << 16) +#define PAGEBURSTACCESSTIME (0x1UL << 24) + +#define GPMC_CONFIG6_0 (GPMC_BASE + 0x74) +#define CYCLE2CYCLESAMECSEN (0x1UL << 7) +#define CYCLE2CYCLEDELAY (0xAUL << 8) +#define WRDATAONADMUXBUS (0xFUL << 16) +#define WRACCESSTIME (0x1FUL << 24) + +#define GPMC_CONFIG7_0 (GPMC_BASE + 0x78) +#define BASEADDRESS (0x30UL << 0) +#define CSVALID (0x1UL << 6) +#define MASKADDRESS_128MB (0x8UL << 8) + +#define GPMC_NAND_COMMAND_0 (GPMC_BASE + 0x7C) +#define GPMC_NAND_ADDRESS_0 (GPMC_BASE + 0x80) +#define GPMC_NAND_DATA_0 (GPMC_BASE + 0x84) + +#define GPMC_ECC_CONFIG (GPMC_BASE + 0x1F4) +#define ECCENABLE (0x1UL << 0) +#define ECCDISABLE (0x0UL << 0) +#define ECCCS_0 (0x0UL << 1) +#define ECC16B (0x1UL << 7) + +#define GPMC_ECC_CONTROL (GPMC_BASE + 0x1F8) +#define ECCPOINTER_REG1 (0x1UL << 0) +#define ECCCLEAR (0x1UL << 8) + +#define GPMC_ECC_SIZE_CONFIG (GPMC_BASE + 0x1FC) +#define ECCSIZE0_512BYTES (0xFFUL << 12) +#define ECCSIZE1_512BYTES (0xFFUL << 22) + +#define GPMC_ECC1_RESULT (GPMC_BASE + 0x200) +#define GPMC_ECC2_RESULT (GPMC_BASE + 0x204) +#define GPMC_ECC3_RESULT (GPMC_BASE + 0x208) +#define GPMC_ECC4_RESULT (GPMC_BASE + 0x20C) +#define GPMC_ECC5_RESULT (GPMC_BASE + 0x210) +#define GPMC_ECC6_RESULT (GPMC_BASE + 0x214) +#define GPMC_ECC7_RESULT (GPMC_BASE + 0x218) +#define GPMC_ECC8_RESULT (GPMC_BASE + 0x21C) +#define GPMC_ECC9_RESULT (GPMC_BASE + 0x220) + +#endif //__OMAP3530GPMC_H__ diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530I2c.h b/BeagleBoardPkg/Include/Omap3530/Omap3530I2c.h new file mode 100644 index 0000000000..5477b61645 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530I2c.h @@ -0,0 +1,62 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __OMAP3530I2C_H__ +#define __OMAP3530I2C_H__ + +//I2C register definitions. +#define I2C1BASE 0x48070000 + +#define I2C_IE (I2C1BASE + 0x4) +#define XRDY_IE (0x1UL << 4) +#define RRDY_IE (0x1UL << 3) +#define ARDY_IE (0x1UL << 2) +#define NACK_IE (0x1UL << 1) + +#define I2C_STAT (I2C1BASE + 0x8) +#define BB (0x1UL << 12) +#define XRDY (0x1UL << 4) +#define RRDY (0x1UL << 3) +#define ARDY (0x1UL << 2) +#define NACK (0x1UL << 1) + +#define I2C_WE (I2C1BASE + 0xC) +#define I2C_SYSS (I2C1BASE + 0x10) +#define I2C_BUF (I2C1BASE + 0x14) +#define I2C_CNT (I2C1BASE + 0x18) +#define I2C_DATA (I2C1BASE + 0x1C) +#define I2C_SYSC (I2C1BASE + 0x20) + +#define I2C_CON (I2C1BASE + 0x24) +#define STT (0x1UL << 0) +#define STP (0x1UL << 1) +#define XSA (0x1UL << 8) +#define TRX (0x1UL << 9) +#define MST (0x1UL << 10) +#define I2C_EN (0x1UL << 15) + +#define I2C_OA0 (I2C1BASE + 0x28) +#define I2C_SA (I2C1BASE + 0x2C) +#define I2C_PSC (I2C1BASE + 0x30) +#define I2C_SCLL (I2C1BASE + 0x34) +#define I2C_SCLH (I2C1BASE + 0x38) +#define I2C_SYSTEST (I2C1BASE + 0x3C) +#define I2C_BUFSTAT (I2C1BASE + 0x40) +#define I2C_OA1 (I2C1BASE + 0x44) +#define I2C_OA2 (I2C1BASE + 0x48) +#define I2C_OA3 (I2C1BASE + 0x4C) +#define I2C_ACTOA (I2C1BASE + 0x50) +#define I2C_SBLOCK (I2C1BASE + 0x54) + +#endif //__OMAP3530I2C_H__ diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Interrupt.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Interrupt.h new file mode 100644 index 0000000000..129d8c0469 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Interrupt.h @@ -0,0 +1,46 @@ +/** @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 __OMAP3530INTERRUPT_H__ +#define __OMAP3530INTERRUPT_H__ + +#define INTERRUPT_BASE (0x48200000) + +#define INT_NROF_VECTORS (96) +#define MAX_VECTOR (INT_NROF_VECTORS - 1) +#define INTCPS_SYSCONFIG (INTERRUPT_BASE + 0x0010) +#define INTCPS_SYSSTATUS (INTERRUPT_BASE + 0x0014) +#define INTCPS_SIR_IRQ (INTERRUPT_BASE + 0x0040) +#define INTCPS_SIR_IFQ (INTERRUPT_BASE + 0x0044) +#define INTCPS_CONTROL (INTERRUPT_BASE + 0x0048) +#define INTCPS_PROTECTION (INTERRUPT_BASE + 0x004C) +#define INTCPS_IDLE (INTERRUPT_BASE + 0x0050) +#define INTCPS_IRQ_PRIORITY (INTERRUPT_BASE + 0x0060) +#define INTCPS_FIQ_PRIORITY (INTERRUPT_BASE + 0x0064) +#define INTCPS_THRESHOLD (INTERRUPT_BASE + 0x0068) +#define INTCPS_ITR(n) (INTERRUPT_BASE + 0x0080 + (0x20 * (n))) +#define INTCPS_MIR(n) (INTERRUPT_BASE + 0x0084 + (0x20 * (n))) +#define INTCPS_MIR_CLEAR(n) (INTERRUPT_BASE + 0x0088 + (0x20 * (n))) +#define INTCPS_MIR_SET(n) (INTERRUPT_BASE + 0x008C + (0x20 * (n))) +#define INTCPS_ISR_SET(n) (INTERRUPT_BASE + 0x0090 + (0x20 * (n))) +#define INTCPS_ISR_CLEAR(n) (INTERRUPT_BASE + 0x0094 + (0x20 * (n))) +#define INTCPS_PENDING_IRQ(n) (INTERRUPT_BASE + 0x0098 + (0x20 * (n))) +#define INTCPS_PENDING_FIQ(n) (INTERRUPT_BASE + 0x009C + (0x20 * (n))) +#define INTCPS_ILR(m) (INTERRUPT_BASE + 0x0100 + (0x04 * (m))) + +#define INTCPS_SIR_IRQ_MASK (0x7F) +#define INTCPS_CONTROL_NEWIRQAGR (1UL << 0) + +#endif // __OMAP3530INTERRUPT_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530MMCHS.h b/BeagleBoardPkg/Include/Omap3530/Omap3530MMCHS.h new file mode 100755 index 0000000000..5ade843801 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530MMCHS.h @@ -0,0 +1,208 @@ +/** @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 __OMAP3530SDIO_H__ +#define __OMAP3530SDIO_H__ + +//MMC/SD/SDIO1 register definitions. +#define MMCHS1BASE 0x4809C000 +#define MMC_REFERENCE_CLK (96000000) + +#define MMCHS_SYSCONFIG (MMCHS1BASE + 0x10) +#define SOFTRESET (0x1UL << 1) +#define ENAWAKEUP (0x1UL << 2) + +#define MMCHS_SYSSTATUS (MMCHS1BASE + 0x14) +#define RESETDONE_MASK (0x1UL << 0) +#define RESETDONE (0x1UL << 0) + +#define MMCHS_CSRE (MMCHS1BASE + 0x24) +#define MMCHS_SYSTEST (MMCHS1BASE + 0x28) + +#define MMCHS_CON (MMCHS1BASE + 0x2C) +#define OD (0x1UL << 0) +#define NOINIT (0x0UL << 1) +#define INIT (0x1UL << 1) +#define HR (0x1UL << 2) +#define STR (0x1UL << 3) +#define MODE (0x1UL << 4) +#define DW8_1_4_BIT (0x0UL << 5) +#define DW8_8_BIT (0x1UL << 5) +#define MIT (0x1UL << 6) +#define CDP (0x1UL << 7) +#define WPP (0x1UL << 8) +#define CTPL (0x1UL << 11) +#define CEATA_OFF (0x0UL << 12) +#define CEATA_ON (0x1UL << 12) + +#define MMCHS_PWCNT (MMCHS1BASE + 0x30) + +#define MMCHS_BLK (MMCHS1BASE + 0x104) +#define BLEN_512BYTES (0x200UL << 0) + +#define MMCHS_ARG (MMCHS1BASE + 0x108) + +#define MMCHS_CMD (MMCHS1BASE + 0x10C) +#define DE_ENABLE (0x1UL << 0) +#define BCE_ENABLE (0x1UL << 1) +#define ACEN_ENABLE (0x1UL << 2) +#define DDIR_READ (0x1UL << 4) +#define DDIR_WRITE (0x0UL << 4) +#define MSBS_SGLEBLK (0x0UL << 5) +#define MSBS_MULTBLK (0x1UL << 5) +#define RSP_TYPE_MASK (0x3UL << 16) +#define RSP_TYPE_136BITS (0x1UL << 16) +#define RSP_TYPE_48BITS (0x2UL << 16) +#define CCCE_ENABLE (0x1UL << 19) +#define CICE_ENABLE (0x1UL << 20) +#define DP_ENABLE (0x1UL << 21) +#define INDX(CMD_INDX) ((CMD_INDX & 0x3F) << 24) + +#define MMCHS_RSP10 (MMCHS1BASE + 0x110) +#define MMCHS_RSP32 (MMCHS1BASE + 0x114) +#define MMCHS_RSP54 (MMCHS1BASE + 0x118) +#define MMCHS_RSP76 (MMCHS1BASE + 0x11C) +#define MMCHS_DATA (MMCHS1BASE + 0x120) + +#define MMCHS_PSTATE (MMCHS1BASE + 0x124) +#define CMDI_MASK (0x1UL << 0) +#define CMDI_ALLOWED (0x0UL << 0) +#define CMDI_NOT_ALLOWED (0x1UL << 0) +#define DATI_MASK (0x1UL << 1) +#define DATI_ALLOWED (0x0UL << 1) +#define DATI_NOT_ALLOWED (0x1UL << 1) + +#define MMCHS_HCTL (MMCHS1BASE + 0x128) +#define DTW_1_BIT (0x0UL << 1) +#define DTW_4_BIT (0x1UL << 1) +#define SDBP_MASK (0x1UL << 8) +#define SDBP_OFF (0x0UL << 8) +#define SDBP_ON (0x1UL << 8) +#define SDVS_1_8_V (0x5UL << 9) +#define SDVS_3_0_V (0x6UL << 9) +#define IWE (0x1UL << 24) + +#define MMCHS_SYSCTL (MMCHS1BASE + 0x12C) +#define ICE (0x1UL << 0) +#define ICS_MASK (0x1UL << 1) +#define ICS (0x1UL << 1) +#define CEN (0x1UL << 2) +#define CLKD_MASK (0x3FFUL << 6) +#define CLKD_80KHZ (0x258UL) //(96*1000/80)/2 +#define CLKD_400KHZ (0xF0UL) +#define DTO_MASK (0xFUL << 16) +#define DTO_VAL (0xEUL << 16) +#define SRA (0x1UL << 24) +#define SRC_MASK (0x1UL << 25) +#define SRC (0x1UL << 25) +#define SRD (0x1UL << 26) + +#define MMCHS_STAT (MMCHS1BASE + 0x130) +#define CC (0x1UL << 0) +#define TC (0x1UL << 1) +#define BWR (0x1UL << 4) +#define BRR (0x1UL << 5) +#define ERRI (0x1UL << 15) +#define CTO (0x1UL << 16) +#define DTO (0x1UL << 20) +#define DCRC (0x1UL << 21) +#define DEB (0x1UL << 22) + +#define MMCHS_IE (MMCHS1BASE + 0x134) +#define CC_EN (0x1UL << 0) +#define TC_EN (0x1UL << 1) +#define BWR_EN (0x1UL << 4) +#define BRR_EN (0x1UL << 5) +#define CTO_EN (0x1UL << 16) +#define CCRC_EN (0x1UL << 17) +#define CEB_EN (0x1UL << 18) +#define CIE_EN (0x1UL << 19) +#define DTO_EN (0x1UL << 20) +#define DCRC_EN (0x1UL << 21) +#define DEB_EN (0x1UL << 22) +#define CERR_EN (0x1UL << 28) +#define BADA_EN (0x1UL << 29) + +#define MMCHS_ISE (MMCHS1BASE + 0x138) +#define CC_SIGEN (0x1UL << 0) +#define TC_SIGEN (0x1UL << 1) +#define BWR_SIGEN (0x1UL << 4) +#define BRR_SIGEN (0x1UL << 5) +#define CTO_SIGEN (0x1UL << 16) +#define CCRC_SIGEN (0x1UL << 17) +#define CEB_SIGEN (0x1UL << 18) +#define CIE_SIGEN (0x1UL << 19) +#define DTO_SIGEN (0x1UL << 20) +#define DCRC_SIGEN (0x1UL << 21) +#define DEB_SIGEN (0x1UL << 22) +#define CERR_SIGEN (0x1UL << 28) +#define BADA_SIGEN (0x1UL << 29) + +#define MMCHS_AC12 (MMCHS1BASE + 0x13C) + +#define MMCHS_CAPA (MMCHS1BASE + 0x140) +#define VS30 (0x1UL << 25) +#define VS18 (0x1UL << 26) + +#define MMCHS_CUR_CAPA (MMCHS1BASE + 0x148) +#define MMCHS_REV (MMCHS1BASE + 0x1FC) + +#define CMD0 INDX(0) +#define CMD0_INT_EN (CC_EN | CEB_EN) + +#define CMD1 (INDX(1) | RSP_TYPE_48BITS) +#define CMD1_INT_EN (CC_EN | CEB_EN | CTO_EN) + +#define CMD2 (INDX(2) | CCCE_ENABLE | RSP_TYPE_136BITS) +#define CMD2_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD3 (INDX(3) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD3_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD5 (INDX(5) | RSP_TYPE_48BITS) +#define CMD5_INT_EN (CC_EN | CEB_EN | CTO_EN) + +#define CMD7 (INDX(7) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD7_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD8 (INDX(8) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD8_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) +//Reserved(0)[12:31], Supply voltage(1)[11:8], check pattern(0xCE)[7:0] = 0x1CE +#define CMD8_ARG (0x0UL << 12 | 0x1UL << 8 | 0xCEUL << 0) + +#define CMD9 (INDX(9) | CCCE_ENABLE | RSP_TYPE_136BITS) +#define CMD9_INT_EN (CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD16 (INDX(16) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD16_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD17 (INDX(17) | DP_ENABLE | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS | DDIR_READ) +#define CMD17_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | TC_EN | BRR_EN | CTO_EN | DTO_EN | DCRC_EN | DEB_EN | CEB_EN) + +#define CMD18 (INDX(18) | DP_ENABLE | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS | MSBS_MULTBLK | DDIR_READ | BCE_ENABLE | DE_ENABLE) +#define CMD18_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | TC_EN | BRR_EN | CTO_EN | DTO_EN | DCRC_EN | DEB_EN | CEB_EN) + +#define CMD23 (INDX(23) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD23_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define CMD24 (INDX(24) | DP_ENABLE | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS | DDIR_WRITE) +#define CMD24_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | TC_EN | BWR_EN | CTO_EN | DTO_EN | DCRC_EN | DEB_EN | CEB_EN) + +#define CMD55 (INDX(55) | CICE_ENABLE | CCCE_ENABLE | RSP_TYPE_48BITS) +#define CMD55_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#define ACMD41 (INDX(41) | RSP_TYPE_48BITS) +#define ACMD41_INT_EN (CERR_EN | CIE_EN | CCRC_EN | CC_EN | CEB_EN | CTO_EN) + +#endif //__OMAP3530SDIO_H__ diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530PadConfiguration.h b/BeagleBoardPkg/Include/Omap3530/Omap3530PadConfiguration.h new file mode 100644 index 0000000000..baae8c68c8 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530PadConfiguration.h @@ -0,0 +1,298 @@ +/** @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 __OMAP3530_PAD_CONFIGURATION_H__ +#define __OMAP3530_PAD_CONFIGURATION_H__ + +#define SYSTEM_CONTROL_MODULE_BASE 0x48002000 + +//Pin definition +#define SDRC_D0 (SYSTEM_CONTROL_MODULE_BASE + 0x030) +#define SDRC_D1 (SYSTEM_CONTROL_MODULE_BASE + 0x032) +#define SDRC_D2 (SYSTEM_CONTROL_MODULE_BASE + 0x034) +#define SDRC_D3 (SYSTEM_CONTROL_MODULE_BASE + 0x036) +#define SDRC_D4 (SYSTEM_CONTROL_MODULE_BASE + 0x038) +#define SDRC_D5 (SYSTEM_CONTROL_MODULE_BASE + 0x03A) +#define SDRC_D6 (SYSTEM_CONTROL_MODULE_BASE + 0x03C) +#define SDRC_D7 (SYSTEM_CONTROL_MODULE_BASE + 0x03E) +#define SDRC_D8 (SYSTEM_CONTROL_MODULE_BASE + 0x040) +#define SDRC_D9 (SYSTEM_CONTROL_MODULE_BASE + 0x042) +#define SDRC_D10 (SYSTEM_CONTROL_MODULE_BASE + 0x044) +#define SDRC_D11 (SYSTEM_CONTROL_MODULE_BASE + 0x046) +#define SDRC_D12 (SYSTEM_CONTROL_MODULE_BASE + 0x048) +#define SDRC_D13 (SYSTEM_CONTROL_MODULE_BASE + 0x04A) +#define SDRC_D14 (SYSTEM_CONTROL_MODULE_BASE + 0x04C) +#define SDRC_D15 (SYSTEM_CONTROL_MODULE_BASE + 0x04E) +#define SDRC_D16 (SYSTEM_CONTROL_MODULE_BASE + 0x050) +#define SDRC_D17 (SYSTEM_CONTROL_MODULE_BASE + 0x052) +#define SDRC_D18 (SYSTEM_CONTROL_MODULE_BASE + 0x054) +#define SDRC_D19 (SYSTEM_CONTROL_MODULE_BASE + 0x056) +#define SDRC_D20 (SYSTEM_CONTROL_MODULE_BASE + 0x058) +#define SDRC_D21 (SYSTEM_CONTROL_MODULE_BASE + 0x05A) +#define SDRC_D22 (SYSTEM_CONTROL_MODULE_BASE + 0x05C) +#define SDRC_D23 (SYSTEM_CONTROL_MODULE_BASE + 0x05E) +#define SDRC_D24 (SYSTEM_CONTROL_MODULE_BASE + 0x060) +#define SDRC_D25 (SYSTEM_CONTROL_MODULE_BASE + 0x062) +#define SDRC_D26 (SYSTEM_CONTROL_MODULE_BASE + 0x064) +#define SDRC_D27 (SYSTEM_CONTROL_MODULE_BASE + 0x066) +#define SDRC_D28 (SYSTEM_CONTROL_MODULE_BASE + 0x068) +#define SDRC_D29 (SYSTEM_CONTROL_MODULE_BASE + 0x06A) +#define SDRC_D30 (SYSTEM_CONTROL_MODULE_BASE + 0x06C) +#define SDRC_D31 (SYSTEM_CONTROL_MODULE_BASE + 0x06E) +#define SDRC_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x070) +#define SDRC_DQS0 (SYSTEM_CONTROL_MODULE_BASE + 0x072) +#define SDRC_CKE0 (SYSTEM_CONTROL_MODULE_BASE + 0x262) +#define SDRC_CKE1 (SYSTEM_CONTROL_MODULE_BASE + 0x264) +#define SDRC_DQS1 (SYSTEM_CONTROL_MODULE_BASE + 0x074) +#define SDRC_DQS2 (SYSTEM_CONTROL_MODULE_BASE + 0x076) +#define SDRC_DQS3 (SYSTEM_CONTROL_MODULE_BASE + 0x078) +#define GPMC_A1 (SYSTEM_CONTROL_MODULE_BASE + 0x07A) +#define GPMC_A2 (SYSTEM_CONTROL_MODULE_BASE + 0x07C) +#define GPMC_A3 (SYSTEM_CONTROL_MODULE_BASE + 0x07E) +#define GPMC_A4 (SYSTEM_CONTROL_MODULE_BASE + 0x080) +#define GPMC_A5 (SYSTEM_CONTROL_MODULE_BASE + 0x082) +#define GPMC_A6 (SYSTEM_CONTROL_MODULE_BASE + 0x084) +#define GPMC_A7 (SYSTEM_CONTROL_MODULE_BASE + 0x086) +#define GPMC_A8 (SYSTEM_CONTROL_MODULE_BASE + 0x088) +#define GPMC_A9 (SYSTEM_CONTROL_MODULE_BASE + 0x08A) +#define GPMC_A10 (SYSTEM_CONTROL_MODULE_BASE + 0x08C) +#define GPMC_D0 (SYSTEM_CONTROL_MODULE_BASE + 0x08E) +#define GPMC_D1 (SYSTEM_CONTROL_MODULE_BASE + 0x090) +#define GPMC_D2 (SYSTEM_CONTROL_MODULE_BASE + 0x092) +#define GPMC_D3 (SYSTEM_CONTROL_MODULE_BASE + 0x094) +#define GPMC_D4 (SYSTEM_CONTROL_MODULE_BASE + 0x096) +#define GPMC_D5 (SYSTEM_CONTROL_MODULE_BASE + 0x098) +#define GPMC_D6 (SYSTEM_CONTROL_MODULE_BASE + 0x09A) +#define GPMC_D7 (SYSTEM_CONTROL_MODULE_BASE + 0x09C) +#define GPMC_D8 (SYSTEM_CONTROL_MODULE_BASE + 0x09E) +#define GPMC_D9 (SYSTEM_CONTROL_MODULE_BASE + 0x0A0) +#define GPMC_D10 (SYSTEM_CONTROL_MODULE_BASE + 0x0A2) +#define GPMC_D11 (SYSTEM_CONTROL_MODULE_BASE + 0x0A4) +#define GPMC_D12 (SYSTEM_CONTROL_MODULE_BASE + 0x0A6) +#define GPMC_D13 (SYSTEM_CONTROL_MODULE_BASE + 0x0A8) +#define GPMC_D14 (SYSTEM_CONTROL_MODULE_BASE + 0x0AA) +#define GPMC_D15 (SYSTEM_CONTROL_MODULE_BASE + 0x0AC) +#define GPMC_NCS0 (SYSTEM_CONTROL_MODULE_BASE + 0x0AE) +#define GPMC_NCS1 (SYSTEM_CONTROL_MODULE_BASE + 0x0B0) +#define GPMC_NCS2 (SYSTEM_CONTROL_MODULE_BASE + 0x0B2) +#define GPMC_NCS3 (SYSTEM_CONTROL_MODULE_BASE + 0x0B4) +#define GPMC_NCS4 (SYSTEM_CONTROL_MODULE_BASE + 0x0B6) +#define GPMC_NCS5 (SYSTEM_CONTROL_MODULE_BASE + 0x0B8) +#define GPMC_NCS6 (SYSTEM_CONTROL_MODULE_BASE + 0x0BA) +#define GPMC_NCS7 (SYSTEM_CONTROL_MODULE_BASE + 0x0BC) +#define GPMC_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x0BE) +#define GPMC_NADV_ALE (SYSTEM_CONTROL_MODULE_BASE + 0x0C0) +#define GPMC_NOE (SYSTEM_CONTROL_MODULE_BASE + 0x0C2) +#define GPMC_NWE (SYSTEM_CONTROL_MODULE_BASE + 0x0C4) +#define GPMC_NBE0_CLE (SYSTEM_CONTROL_MODULE_BASE + 0x0C6) +#define GPMC_NBE1 (SYSTEM_CONTROL_MODULE_BASE + 0x0C8) +#define GPMC_NWP (SYSTEM_CONTROL_MODULE_BASE + 0x0CA) +#define GPMC_WAIT0 (SYSTEM_CONTROL_MODULE_BASE + 0x0CC) +#define GPMC_WAIT1 (SYSTEM_CONTROL_MODULE_BASE + 0x0CE) +#define GPMC_WAIT2 (SYSTEM_CONTROL_MODULE_BASE + 0x0D0) +#define GPMC_WAIT3 (SYSTEM_CONTROL_MODULE_BASE + 0x0D2) +#define DSS_PCLK (SYSTEM_CONTROL_MODULE_BASE + 0x0D4) +#define DSS_HSYNC (SYSTEM_CONTROL_MODULE_BASE + 0x0D6) +#define DSS_PSYNC (SYSTEM_CONTROL_MODULE_BASE + 0x0D8) +#define DSS_ACBIAS (SYSTEM_CONTROL_MODULE_BASE + 0x0DA) +#define DSS_DATA0 (SYSTEM_CONTROL_MODULE_BASE + 0x0DC) +#define DSS_DATA1 (SYSTEM_CONTROL_MODULE_BASE + 0x0DE) +#define DSS_DATA2 (SYSTEM_CONTROL_MODULE_BASE + 0x0E0) +#define DSS_DATA3 (SYSTEM_CONTROL_MODULE_BASE + 0x0E2) +#define DSS_DATA4 (SYSTEM_CONTROL_MODULE_BASE + 0x0E4) +#define DSS_DATA5 (SYSTEM_CONTROL_MODULE_BASE + 0x0E6) +#define DSS_DATA6 (SYSTEM_CONTROL_MODULE_BASE + 0x0E8) +#define DSS_DATA7 (SYSTEM_CONTROL_MODULE_BASE + 0x0EA) +#define DSS_DATA8 (SYSTEM_CONTROL_MODULE_BASE + 0x0EC) +#define DSS_DATA9 (SYSTEM_CONTROL_MODULE_BASE + 0x0EE) +#define DSS_DATA10 (SYSTEM_CONTROL_MODULE_BASE + 0x0F0) +#define DSS_DATA11 (SYSTEM_CONTROL_MODULE_BASE + 0x0F2) +#define DSS_DATA12 (SYSTEM_CONTROL_MODULE_BASE + 0x0F4) +#define DSS_DATA13 (SYSTEM_CONTROL_MODULE_BASE + 0x0F6) +#define DSS_DATA14 (SYSTEM_CONTROL_MODULE_BASE + 0x0F8) +#define DSS_DATA15 (SYSTEM_CONTROL_MODULE_BASE + 0x0FA) +#define DSS_DATA16 (SYSTEM_CONTROL_MODULE_BASE + 0x0FC) +#define DSS_DATA17 (SYSTEM_CONTROL_MODULE_BASE + 0x0FE) +#define DSS_DATA18 (SYSTEM_CONTROL_MODULE_BASE + 0x100) +#define DSS_DATA19 (SYSTEM_CONTROL_MODULE_BASE + 0x102) +#define DSS_DATA20 (SYSTEM_CONTROL_MODULE_BASE + 0x104) +#define DSS_DATA21 (SYSTEM_CONTROL_MODULE_BASE + 0x106) +#define DSS_DATA22 (SYSTEM_CONTROL_MODULE_BASE + 0x108) +#define DSS_DATA23 (SYSTEM_CONTROL_MODULE_BASE + 0x10A) +#define CAM_HS (SYSTEM_CONTROL_MODULE_BASE + 0x10C) +#define CAM_VS (SYSTEM_CONTROL_MODULE_BASE + 0x10E) +#define CAM_XCLKA (SYSTEM_CONTROL_MODULE_BASE + 0x110) +#define CAM_PCLK (SYSTEM_CONTROL_MODULE_BASE + 0x112) +#define CAM_FLD (SYSTEM_CONTROL_MODULE_BASE + 0x114) +#define CAM_D0 (SYSTEM_CONTROL_MODULE_BASE + 0x116) +#define CAM_D1 (SYSTEM_CONTROL_MODULE_BASE + 0x118) +#define CAM_D2 (SYSTEM_CONTROL_MODULE_BASE + 0x11A) +#define CAM_D3 (SYSTEM_CONTROL_MODULE_BASE + 0x11C) +#define CAM_D4 (SYSTEM_CONTROL_MODULE_BASE + 0x11E) +#define CAM_D5 (SYSTEM_CONTROL_MODULE_BASE + 0x120) +#define CAM_D6 (SYSTEM_CONTROL_MODULE_BASE + 0x122) +#define CAM_D7 (SYSTEM_CONTROL_MODULE_BASE + 0x124) +#define CAM_D8 (SYSTEM_CONTROL_MODULE_BASE + 0x126) +#define CAM_D9 (SYSTEM_CONTROL_MODULE_BASE + 0x128) +#define CAM_D10 (SYSTEM_CONTROL_MODULE_BASE + 0x12A) +#define CAM_D11 (SYSTEM_CONTROL_MODULE_BASE + 0x12C) +#define CAM_XCLKB (SYSTEM_CONTROL_MODULE_BASE + 0x12E) +#define CAM_WEN (SYSTEM_CONTROL_MODULE_BASE + 0x130) +#define CAM_STROBE (SYSTEM_CONTROL_MODULE_BASE + 0x132) +#define CSI2_DX0 (SYSTEM_CONTROL_MODULE_BASE + 0x134) +#define CSI2_DY0 (SYSTEM_CONTROL_MODULE_BASE + 0x136) +#define CSI2_DX1 (SYSTEM_CONTROL_MODULE_BASE + 0x138) +#define CSI2_DY1 (SYSTEM_CONTROL_MODULE_BASE + 0x13A) +#define MCBSP2_FSX (SYSTEM_CONTROL_MODULE_BASE + 0x13C) +#define MCBSP2_CLKX (SYSTEM_CONTROL_MODULE_BASE + 0x13E) +#define MCBSP2_DR (SYSTEM_CONTROL_MODULE_BASE + 0x140) +#define MCBSP2_DX (SYSTEM_CONTROL_MODULE_BASE + 0x142) +#define MMC1_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x144) +#define MMC1_CMD (SYSTEM_CONTROL_MODULE_BASE + 0x146) +#define MMC1_DAT0 (SYSTEM_CONTROL_MODULE_BASE + 0x148) +#define MMC1_DAT1 (SYSTEM_CONTROL_MODULE_BASE + 0x14A) +#define MMC1_DAT2 (SYSTEM_CONTROL_MODULE_BASE + 0x14C) +#define MMC1_DAT3 (SYSTEM_CONTROL_MODULE_BASE + 0x14E) +#define MMC1_DAT4 (SYSTEM_CONTROL_MODULE_BASE + 0x150) +#define MMC1_DAT5 (SYSTEM_CONTROL_MODULE_BASE + 0x152) +#define MMC1_DAT6 (SYSTEM_CONTROL_MODULE_BASE + 0x154) +#define MMC1_DAT7 (SYSTEM_CONTROL_MODULE_BASE + 0x156) +#define MMC2_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x158) +#define MMC2_CMD (SYSTEM_CONTROL_MODULE_BASE + 0x15A) +#define MMC2_DAT0 (SYSTEM_CONTROL_MODULE_BASE + 0x15C) +#define MMC2_DAT1 (SYSTEM_CONTROL_MODULE_BASE + 0x15E) +#define MMC2_DAT2 (SYSTEM_CONTROL_MODULE_BASE + 0x160) +#define MMC2_DAT3 (SYSTEM_CONTROL_MODULE_BASE + 0x162) +#define MMC2_DAT4 (SYSTEM_CONTROL_MODULE_BASE + 0x164) +#define MMC2_DAT5 (SYSTEM_CONTROL_MODULE_BASE + 0x166) +#define MMC2_DAT6 (SYSTEM_CONTROL_MODULE_BASE + 0x168) +#define MMC2_DAT7 (SYSTEM_CONTROL_MODULE_BASE + 0x16A) +#define MCBSP3_DX (SYSTEM_CONTROL_MODULE_BASE + 0x16C) +#define MCBSP3_DR (SYSTEM_CONTROL_MODULE_BASE + 0x16E) +#define MCBSP3_CLKX (SYSTEM_CONTROL_MODULE_BASE + 0x170) +#define MCBSP3_FSX (SYSTEM_CONTROL_MODULE_BASE + 0x172) +#define UART2_CTS (SYSTEM_CONTROL_MODULE_BASE + 0x174) +#define UART2_RTS (SYSTEM_CONTROL_MODULE_BASE + 0x176) +#define UART2_TX (SYSTEM_CONTROL_MODULE_BASE + 0x178) +#define UART2_RX (SYSTEM_CONTROL_MODULE_BASE + 0x17A) +#define UART1_TX (SYSTEM_CONTROL_MODULE_BASE + 0x17C) +#define UART1_RTS (SYSTEM_CONTROL_MODULE_BASE + 0x17E) +#define UART1_CTS (SYSTEM_CONTROL_MODULE_BASE + 0x180) +#define UART1_RX (SYSTEM_CONTROL_MODULE_BASE + 0x182) +#define MCBSP4_CLKX (SYSTEM_CONTROL_MODULE_BASE + 0x184) +#define MCBSP4_DR (SYSTEM_CONTROL_MODULE_BASE + 0x186) +#define MCBSP4_DX (SYSTEM_CONTROL_MODULE_BASE + 0x188) +#define MCBSP4_FSX (SYSTEM_CONTROL_MODULE_BASE + 0x18A) +#define MCBSP1_CLKR (SYSTEM_CONTROL_MODULE_BASE + 0x18C) +#define MCBSP1_FSR (SYSTEM_CONTROL_MODULE_BASE + 0x18E) +#define MCBSP1_DX (SYSTEM_CONTROL_MODULE_BASE + 0x190) +#define MCBSP1_DR (SYSTEM_CONTROL_MODULE_BASE + 0x192) +#define MCBSP1_CLKS (SYSTEM_CONTROL_MODULE_BASE + 0x194) +#define MCBSP1_FSX (SYSTEM_CONTROL_MODULE_BASE + 0x196) +#define MCBSP1_CLKX (SYSTEM_CONTROL_MODULE_BASE + 0x198) +#define UART3_CTS_RCTX (SYSTEM_CONTROL_MODULE_BASE + 0x19A) +#define UART3_RTS_SD (SYSTEM_CONTROL_MODULE_BASE + 0x19C) +#define UART3_RX_IRRX (SYSTEM_CONTROL_MODULE_BASE + 0x19E) +#define UART3_TX_IRTX (SYSTEM_CONTROL_MODULE_BASE + 0x1A0) +#define HSUSB0_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x1A2) +#define HSUSB0_STP (SYSTEM_CONTROL_MODULE_BASE + 0x1A4) +#define HSUSB0_DIR (SYSTEM_CONTROL_MODULE_BASE + 0x1A6) +#define HSUSB0_NXT (SYSTEM_CONTROL_MODULE_BASE + 0x1A8) +#define HSUSB0_DATA0 (SYSTEM_CONTROL_MODULE_BASE + 0x1AA) +#define HSUSB0_DATA1 (SYSTEM_CONTROL_MODULE_BASE + 0x1AC) +#define HSUSB0_DATA2 (SYSTEM_CONTROL_MODULE_BASE + 0x1AE) +#define HSUSB0_DATA3 (SYSTEM_CONTROL_MODULE_BASE + 0x1B0) +#define HSUSB0_DATA4 (SYSTEM_CONTROL_MODULE_BASE + 0x1B2) +#define HSUSB0_DATA5 (SYSTEM_CONTROL_MODULE_BASE + 0x1B4) +#define HSUSB0_DATA6 (SYSTEM_CONTROL_MODULE_BASE + 0x1B6) +#define HSUSB0_DATA7 (SYSTEM_CONTROL_MODULE_BASE + 0x1B8) +#define I2C1_SCL (SYSTEM_CONTROL_MODULE_BASE + 0x1BA) +#define I2C1_SDA (SYSTEM_CONTROL_MODULE_BASE + 0x1BC) +#define I2C2_SCL (SYSTEM_CONTROL_MODULE_BASE + 0x1BE) +#define I2C2_SDA (SYSTEM_CONTROL_MODULE_BASE + 0x1C0) +#define I2C3_SCL (SYSTEM_CONTROL_MODULE_BASE + 0x1C2) +#define I2C3_SDA (SYSTEM_CONTROL_MODULE_BASE + 0x1C4) +#define HDQ_SIO (SYSTEM_CONTROL_MODULE_BASE + 0x1C6) +#define MCSPI1_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x1C8) +#define MCSPI1_SIMO (SYSTEM_CONTROL_MODULE_BASE + 0x1CA) +#define MCSPI1_SOMI (SYSTEM_CONTROL_MODULE_BASE + 0x1CC) +#define MCSPI1_CS0 (SYSTEM_CONTROL_MODULE_BASE + 0x1CE) +#define MCSPI1_CS1 (SYSTEM_CONTROL_MODULE_BASE + 0x1D0) +#define MCSPI1_CS2 (SYSTEM_CONTROL_MODULE_BASE + 0x1D2) +#define MCSPI1_CS3 (SYSTEM_CONTROL_MODULE_BASE + 0x1D4) +#define MCSPI2_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x1D6) +#define MCSPI2_SIMO (SYSTEM_CONTROL_MODULE_BASE + 0x1D8) +#define MCSPI2_SOMI (SYSTEM_CONTROL_MODULE_BASE + 0x1DA) +#define MCSPI2_CS0 (SYSTEM_CONTROL_MODULE_BASE + 0x1DC) +#define MCSPI2_CS1 (SYSTEM_CONTROL_MODULE_BASE + 0x1DE) +#define SYS_NIRQ (SYSTEM_CONTROL_MODULE_BASE + 0x1E0) +#define SYS_CLKOUT2 (SYSTEM_CONTROL_MODULE_BASE + 0x1E2) +#define ETK_CLK (SYSTEM_CONTROL_MODULE_BASE + 0x5D8) +#define ETK_CTL (SYSTEM_CONTROL_MODULE_BASE + 0x5DA) +#define ETK_D0 (SYSTEM_CONTROL_MODULE_BASE + 0x5DC) +#define ETK_D1 (SYSTEM_CONTROL_MODULE_BASE + 0x5DE) +#define ETK_D2 (SYSTEM_CONTROL_MODULE_BASE + 0x5E0) +#define ETK_D3 (SYSTEM_CONTROL_MODULE_BASE + 0x5E2) +#define ETK_D4 (SYSTEM_CONTROL_MODULE_BASE + 0x5E4) +#define ETK_D5 (SYSTEM_CONTROL_MODULE_BASE + 0x5E6) +#define ETK_D6 (SYSTEM_CONTROL_MODULE_BASE + 0x5E8) +#define ETK_D7 (SYSTEM_CONTROL_MODULE_BASE + 0x5EA) +#define ETK_D8 (SYSTEM_CONTROL_MODULE_BASE + 0x5EC) +#define ETK_D9 (SYSTEM_CONTROL_MODULE_BASE + 0x5EE) +#define ETK_D10 (SYSTEM_CONTROL_MODULE_BASE + 0x5F0) +#define ETK_D11 (SYSTEM_CONTROL_MODULE_BASE + 0x5F2) +#define ETK_D12 (SYSTEM_CONTROL_MODULE_BASE + 0x5F4) +#define ETK_D13 (SYSTEM_CONTROL_MODULE_BASE + 0x5F6) +#define ETK_D14 (SYSTEM_CONTROL_MODULE_BASE + 0x5F8) +#define ETK_D15 (SYSTEM_CONTROL_MODULE_BASE + 0x5FA) + +//Mux modes +#define MUXMODE0 (0x0UL) +#define MUXMODE1 (0x1UL) +#define MUXMODE2 (0x2UL) +#define MUXMODE3 (0x3UL) +#define MUXMODE4 (0x4UL) +#define MUXMODE5 (0x5UL) +#define MUXMODE6 (0x6UL) +#define MUXMODE7 (0x7UL) + +//Pad configuration register. +#define PAD_CONFIG_MASK (0xFFFFUL) +#define MUXMODE_OFFSET 0 +#define MUXMODE_MASK (0x7UL << MUXMODE_OFFSET) +#define PULL_CONFIG_OFFSET 3 +#define PULL_CONFIG_MASK (0x3UL << PULL_CONFIG_OFFSET) +#define INPUTENABLE_OFFSET 8 +#define INPUTENABLE_MASK (0x1UL << INPUTENABLE_OFFSET) +#define OFFMODE_VALUE_OFFSET 9 +#define OFFMODE_VALUE_MASK (0x1FUL << OFFMODE_VALUE_OFFSET) +#define WAKEUP_OFFSET 14 +#define WAKEUP_MASK (0x2UL << WAKEUP_OFFSET) + +#define PULLUDDISABLE (0x0UL << 0) +#define PULLUDENABLE (0x1UL << 0) +#define PULLTYPENOSELECT (0x0UL << 1) +#define PULLTYPESELECT (0x1UL << 1) + +#define OUTPUT (0x0UL) //Pin is configured in output only mode. +#define INPUT (0x1UL) //Pin is configured in bi-directional mode. + +typedef struct { + UINTN Pin; + UINTN MuxMode; + UINTN PullConfig; + UINTN InputEnable; +} PAD_CONFIGURATION; + +#endif //__OMAP3530_PAD_CONFIGURATION_H__ diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Prcm.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Prcm.h new file mode 100644 index 0000000000..036f8bcece --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Prcm.h @@ -0,0 +1,164 @@ +/** @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 __OMAP3530PRCM_H__ +#define __OMAP3530PRCM_H__ + +#define CM_FCLKEN1_CORE (0x48004A00) +#define CM_FCLKEN3_CORE (0x48004A08) +#define CM_ICLKEN1_CORE (0x48004A10) +#define CM_ICLKEN3_CORE (0x48004A18) +#define CM_CLKEN2_PLL (0x48004D04) +#define CM_CLKSEL4_PLL (0x48004D4C) +#define CM_CLKSEL5_PLL (0x48004D50) +#define CM_FCLKEN_USBHOST (0x48005400) +#define CM_ICLKEN_USBHOST (0x48005410) + +//Wakeup clock defintion +#define CM_FCLKEN_WKUP (0x48004C00) +#define CM_ICLKEN_WKUP (0x48004C10) + +//Peripheral clock definition +#define CM_FCLKEN_PER (0x48005000) +#define CM_ICLKEN_PER (0x48005010) +#define CM_CLKSEL_PER (0x48005040) + +//Reset management definition +#define PRM_RSTCTRL (0x48307250) +#define PRM_RSTST (0x48307258) + +//CORE clock +#define CM_FCLKEN1_CORE_EN_I2C1_MASK (1UL << 15) +#define CM_FCLKEN1_CORE_EN_I2C1_DISABLE (0UL << 15) +#define CM_FCLKEN1_CORE_EN_I2C1_ENABLE (1UL << 15) + +#define CM_ICLKEN1_CORE_EN_I2C1_MASK (1UL << 15) +#define CM_ICLKEN1_CORE_EN_I2C1_DISABLE (0UL << 15) +#define CM_ICLKEN1_CORE_EN_I2C1_ENABLE (1UL << 15) + +#define CM_FCLKEN1_CORE_EN_MMC1_MASK (1UL << 24) +#define CM_FCLKEN1_CORE_EN_MMC1_DISABLE (0UL << 24) +#define CM_FCLKEN1_CORE_EN_MMC1_ENABLE (1UL << 24) + +#define CM_FCLKEN3_CORE_EN_USBTLL_MASK (1UL << 2) +#define CM_FCLKEN3_CORE_EN_USBTLL_DISABLE (0UL << 2) +#define CM_FCLKEN3_CORE_EN_USBTLL_ENABLE (1UL << 2) + +#define CM_ICLKEN1_CORE_EN_MMC1_MASK (1UL << 24) +#define CM_ICLKEN1_CORE_EN_MMC1_DISABLE (0UL << 24) +#define CM_ICLKEN1_CORE_EN_MMC1_ENABLE (1UL << 24) + +#define CM_ICLKEN3_CORE_EN_USBTLL_MASK (1UL << 2) +#define CM_ICLKEN3_CORE_EN_USBTLL_DISABLE (0UL << 2) +#define CM_ICLKEN3_CORE_EN_USBTLL_ENABLE (1UL << 2) + +#define CM_CLKEN_FREQSEL_075_100 (0x03UL << 4) +#define CM_CLKEN_ENABLE (7UL << 0) + +#define CM_CLKSEL_PLL_MULT(x) (((x) & 0x07FF) << 8) +#define CM_CLKSEL_PLL_DIV(x) ((((x) - 1) & 0x7F) << 0) + +#define CM_CLKSEL_DIV_120M(x) (((x) & 0x1F) << 0) + +#define CM_FCLKEN_USBHOST_EN_USBHOST2_MASK (1UL << 1) +#define CM_FCLKEN_USBHOST_EN_USBHOST2_DISABLE (0UL << 1) +#define CM_FCLKEN_USBHOST_EN_USBHOST2_ENABLE (1UL << 1) + +#define CM_FCLKEN_USBHOST_EN_USBHOST1_MASK (1UL << 0) +#define CM_FCLKEN_USBHOST_EN_USBHOST1_DISABLE (0UL << 0) +#define CM_FCLKEN_USBHOST_EN_USBHOST1_ENABLE (1UL << 0) + +#define CM_ICLKEN_USBHOST_EN_USBHOST_MASK (1UL << 0) +#define CM_ICLKEN_USBHOST_EN_USBHOST_DISABLE (0UL << 0) +#define CM_ICLKEN_USBHOST_EN_USBHOST_ENABLE (1UL << 0) + +//Wakeup functional clock +#define CM_FCLKEN_WKUP_EN_GPIO1_DISABLE (0UL << 3) +#define CM_FCLKEN_WKUP_EN_GPIO1_ENABLE (1UL << 3) + +#define CM_FCLKEN_WKUP_EN_WDT2_DISABLE (0UL << 5) +#define CM_FCLKEN_WKUP_EN_WDT2_ENABLE (1UL << 5) + +//Wakeup interface clock +#define CM_ICLKEN_WKUP_EN_GPIO1_DISABLE (0UL << 3) +#define CM_ICLKEN_WKUP_EN_GPIO1_ENABLE (1UL << 3) + +#define CM_ICLKEN_WKUP_EN_WDT2_DISABLE (0UL << 5) +#define CM_ICLKEN_WKUP_EN_WDT2_ENABLE (1UL << 5) + +//Peripheral functional clock +#define CM_FCLKEN_PER_EN_GPT3_DISABLE (0UL << 4) +#define CM_FCLKEN_PER_EN_GPT3_ENABLE (1UL << 4) + +#define CM_FCLKEN_PER_EN_GPT4_DISABLE (0UL << 5) +#define CM_FCLKEN_PER_EN_GPT4_ENABLE (1UL << 5) + +#define CM_FCLKEN_PER_EN_UART3_DISABLE (0UL << 11) +#define CM_FCLKEN_PER_EN_UART3_ENABLE (1UL << 11) + +#define CM_FCLKEN_PER_EN_GPIO2_DISABLE (0UL << 13) +#define CM_FCLKEN_PER_EN_GPIO2_ENABLE (1UL << 13) + +#define CM_FCLKEN_PER_EN_GPIO3_DISABLE (0UL << 14) +#define CM_FCLKEN_PER_EN_GPIO3_ENABLE (1UL << 14) + +#define CM_FCLKEN_PER_EN_GPIO4_DISABLE (0UL << 15) +#define CM_FCLKEN_PER_EN_GPIO4_ENABLE (1UL << 15) + +#define CM_FCLKEN_PER_EN_GPIO5_DISABLE (0UL << 16) +#define CM_FCLKEN_PER_EN_GPIO5_ENABLE (1UL << 16) + +#define CM_FCLKEN_PER_EN_GPIO6_DISABLE (0UL << 17) +#define CM_FCLKEN_PER_EN_GPIO6_ENABLE (1UL << 17) + +//Peripheral interface clock +#define CM_ICLKEN_PER_EN_GPT3_DISABLE (0UL << 4) +#define CM_ICLKEN_PER_EN_GPT3_ENABLE (1UL << 4) + +#define CM_ICLKEN_PER_EN_GPT4_DISABLE (0UL << 5) +#define CM_ICLKEN_PER_EN_GPT4_ENABLE (1UL << 5) + +#define CM_ICLKEN_PER_EN_UART3_DISABLE (0UL << 11) +#define CM_ICLKEN_PER_EN_UART3_ENABLE (1UL << 11) + +#define CM_ICLKEN_PER_EN_GPIO2_DISABLE (0UL << 13) +#define CM_ICLKEN_PER_EN_GPIO2_ENABLE (1UL << 13) + +#define CM_ICLKEN_PER_EN_GPIO3_DISABLE (0UL << 14) +#define CM_ICLKEN_PER_EN_GPIO3_ENABLE (1UL << 14) + +#define CM_ICLKEN_PER_EN_GPIO4_DISABLE (0UL << 15) +#define CM_ICLKEN_PER_EN_GPIO4_ENABLE (1UL << 15) + +#define CM_ICLKEN_PER_EN_GPIO5_DISABLE (0UL << 16) +#define CM_ICLKEN_PER_EN_GPIO5_ENABLE (1UL << 16) + +#define CM_ICLKEN_PER_EN_GPIO6_DISABLE (0UL << 17) +#define CM_ICLKEN_PER_EN_GPIO6_ENABLE (1UL << 17) + +//Timer source clock selection +#define CM_CLKSEL_PER_CLKSEL_GPT3_32K (0UL << 1) +#define CM_CLKSEL_PER_CLKSEL_GPT3_SYS (1UL << 1) + +#define CM_CLKSEL_PER_CLKSEL_GPT4_32K (0UL << 2) +#define CM_CLKSEL_PER_CLKSEL_GPT4_SYS (1UL << 2) + +//Reset management (Global and Cold reset) +#define RST_GS (0x1UL << 1) +#define RST_DPLL3 (0x1UL << 2) +#define GLOBAL_SW_RST (0x1UL << 1) +#define GLOBAL_COLD_RST (0x0UL << 0) + +#endif // __OMAP3530PRCM_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Timer.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Timer.h new file mode 100644 index 0000000000..1c43b3ee32 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Timer.h @@ -0,0 +1,82 @@ +/** @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 __OMAP3530TIMER_H__ +#define __OMAP3530TIMER_H__ + +#define GPTIMER1_BASE (0x48313000) +#define GPTIMER2_BASE (0x49032000) +#define GPTIMER3_BASE (0x49034000) +#define GPTIMER4_BASE (0x49036000) +#define GPTIMER5_BASE (0x49038000) +#define GPTIMER6_BASE (0x4903A000) +#define GPTIMER7_BASE (0x4903C000) +#define GPTIMER8_BASE (0x4903E000) +#define GPTIMER9_BASE (0x49040000) +#define GPTIMER10_BASE (0x48086000) +#define GPTIMER11_BASE (0x48088000) +#define GPTIMER12_BASE (0x48304000) +#define WDTIMER2_BASE (0x48314000) + +#define GPTIMER_TIOCP_CFG (0x0010) +#define GPTIMER_TISTAT (0x0014) +#define GPTIMER_TISR (0x0018) +#define GPTIMER_TIER (0x001C) +#define GPTIMER_TWER (0x0020) +#define GPTIMER_TCLR (0x0024) +#define GPTIMER_TCRR (0x0028) +#define GPTIMER_TLDR (0x002C) +#define GPTIMER_TTGR (0x0030) +#define GPTIMER_TWPS (0x0034) +#define GPTIMER_TMAR (0x0038) +#define GPTIMER_TCAR1 (0x003C) +#define GPTIMER_TSICR (0x0040) +#define GPTIMER_TCAR2 (0x0044) +#define GPTIMER_TPIR (0x0048) +#define GPTIMER_TNIR (0x004C) +#define GPTIMER_TCVR (0x0050) +#define GPTIMER_TOCR (0x0054) +#define GPTIMER_TOWR (0x0058) + +#define WSPR (0x048) + +#define TISR_TCAR_IT_FLAG_MASK (1UL << 2) +#define TISR_OVF_IT_FLAG_MASK (1UL << 1) +#define TISR_MAT_IT_FLAG_MASK (1UL << 0) +#define TISR_ALL_INTERRUPT_MASK (TISR_TCAR_IT_FLAG_MASK | TISR_OVF_IT_FLAG_MASK | TISR_MAT_IT_FLAG_MASK) + +#define TISR_TCAR_IT_FLAG_NOT_PENDING (0UL << 2) +#define TISR_OVF_IT_FLAG_NOT_PENDING (0UL << 1) +#define TISR_MAT_IT_FLAG_NOT_PENDING (0UL << 0) +#define TISR_NO_INTERRUPTS_PENDING (TISR_TCAR_IT_FLAG_NOT_PENDING | TISR_OVF_IT_FLAG_NOT_PENDING | TISR_MAT_IT_FLAG_NOT_PENDING) + +#define TISR_TCAR_IT_FLAG_CLEAR (1UL << 2) +#define TISR_OVF_IT_FLAG_CLEAR (1UL << 1) +#define TISR_MAT_IT_FLAG_CLEAR (1UL << 0) +#define TISR_CLEAR_ALL (TISR_TCAR_IT_FLAG_CLEAR | TISR_OVF_IT_FLAG_CLEAR | TISR_MAT_IT_FLAG_CLEAR) + +#define TCLR_AR_AUTORELOAD (1UL << 1) +#define TCLR_AR_ONESHOT (0UL << 1) +#define TCLR_ST_ON (1UL << 0) +#define TCLR_ST_OFF (0UL << 0) + +#define TIER_TCAR_IT_ENABLE (1UL << 2) +#define TIER_TCAR_IT_DISABLE (0UL << 2) +#define TIER_OVF_IT_ENABLE (1UL << 1) +#define TIER_OVF_IT_DISABLE (0UL << 1) +#define TIER_MAT_IT_ENABLE (1UL << 0) +#define TIER_MAT_IT_DISABLE (0UL << 0) + +#endif // __OMAP3530TIMER_H__ + diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Uart.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Uart.h new file mode 100644 index 0000000000..aef1c4bab9 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Uart.h @@ -0,0 +1,53 @@ +/** @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 __OMAP3530UART_H__
+#define __OMAP3530UART_H__
+
+#define UART1_BASE (0x4806A000)
+#define UART2_BASE (0x4806C000)
+#define UART3_BASE (0x49020000)
+
+#define UART_DLL_REG (0x0000)
+#define UART_RBR_REG (0x0000)
+#define UART_THR_REG (0x0000)
+#define UART_DLH_REG (0x0004)
+#define UART_FCR_REG (0x0008)
+#define UART_LCR_REG (0x000C)
+#define UART_MCR_REG (0x0010)
+#define UART_LSR_REG (0x0014)
+#define UART_MDR1_REG (0x0020)
+
+#define UART_FCR_TX_FIFO_CLEAR (1UL << 3)
+#define UART_FCR_RX_FIFO_CLEAR (1UL << 3)
+#define UART_FCR_FIFO_ENABLE (1UL << 3)
+
+#define UART_LCR_DIV_EN_ENABLE (1UL << 7)
+#define UART_LCR_DIV_EN_DISABLE (0UL << 7)
+#define UART_LCR_CHAR_LENGTH_8 (3UL << 0)
+
+#define UART_MCR_RTS_FORCE_ACTIVE (1UL << 1)
+#define UART_MCR_DTR_FORCE_ACTIVE (1UL << 0)
+
+#define UART_LSR_TX_FIFO_E_MASK (1UL << 5)
+#define UART_LSR_TX_FIFO_E_NOT_EMPTY (0UL << 5)
+#define UART_LSR_TX_FIFO_E_EMPTY (1UL << 5)
+#define UART_LSR_RX_FIFO_E_MASK (1UL << 0)
+#define UART_LSR_RX_FIFO_E_NOT_EMPTY (1UL << 0)
+#define UART_LSR_RX_FIFO_E_EMPTY (0UL << 0)
+
+#define UART_MDR1_MODE_SELECT_DISABLE (7UL << 0)
+#define UART_MDR1_MODE_SELECT_UART_16X (0UL << 0)
+
+#endif // __OMAP3530UART_H__
diff --git a/BeagleBoardPkg/Include/Omap3530/Omap3530Usb.h b/BeagleBoardPkg/Include/Omap3530/Omap3530Usb.h new file mode 100644 index 0000000000..5ffaa9d8e4 --- /dev/null +++ b/BeagleBoardPkg/Include/Omap3530/Omap3530Usb.h @@ -0,0 +1,42 @@ +/** @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 __OMAP3530USB_H__ +#define __OMAP3530USB_H__ + +#define USB_BASE (0x48060000) + +#define UHH_SYSCONFIG (USB_BASE + 0x4010) +#define UHH_HOSTCONFIG (USB_BASE + 0x4040) + +#define USB_EHCI_HCCAPBASE (USB_BASE + 0x4800) + +#define UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY (1UL << 12) +#define UHH_SYSCONFIG_CLOCKACTIVITY_ON (1UL << 8) +#define UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY (1UL << 3) +#define UHH_SYSCONFIG_ENAWAKEUP_ENABLE (1UL << 2) +#define UHH_SYSCONFIG_AUTOIDLE_ALWAYS_RUN (0UL << 0) + +#define UHH_HOSTCONFIG_P3_CONNECT_STATUS_DISCONNECT (0UL << 10) +#define UHH_HOSTCONFIG_P2_CONNECT_STATUS_DISCONNECT (0UL << 9) +#define UHH_HOSTCONFIG_P1_CONNECT_STATUS_DISCONNECT (0UL << 8) +#define UHH_HOSTCONFIG_ENA_INCR_ALIGN_DISABLE (0UL << 5) +#define UHH_HOSTCONFIG_ENA_INCR16_ENABLE (1UL << 4) +#define UHH_HOSTCONFIG_ENA_INCR8_ENABLE (1UL << 3) +#define UHH_HOSTCONFIG_ENA_INCR4_ENABLE (1UL << 2) +#define UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN_ON (0UL << 1) +#define UHH_HOSTCONFIG_P1_ULPI_BYPASS_ULPI_MODE (0UL << 0) + +#endif // __OMAP3530USB_H__ + diff --git a/BeagleBoardPkg/Include/TPS65950.h b/BeagleBoardPkg/Include/TPS65950.h new file mode 100644 index 0000000000..4b69099219 --- /dev/null +++ b/BeagleBoardPkg/Include/TPS65950.h @@ -0,0 +1,46 @@ +/** @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 __TPS65950_H__ +#define __TPS65950_H__ + +#define EXTERNAL_DEVICE_REGISTER_TO_SLAVE_ADDRESS(x) (((x) >> 8) & 0xFF) +#define EXTERNAL_DEVICE_REGISTER_TO_REGISTER(x) ((x) & 0xFF) +#define EXTERNAL_DEVICE_REGISTER(SlaveAddress, Register) (((SlaveAddress) & 0xFF) << 8 | ((Register) & 0xFF)) + +//I2C Address group +#define I2C_ADDR_GRP_ID1 0x48 +#define I2C_ADDR_GRP_ID2 0x49 +#define I2C_ADDR_GRP_ID3 0x4A +#define I2C_ADDR_GRP_ID4 0x4B +#define I2C_ADDR_GRP_ID5 0x12 + +//MMC definitions. +#define VMMC1_DEV_GRP 0x82 +#define DEV_GRP_P1 (0x01UL << 5) + +#define VMMC1_DEDICATED_REG 0x85 +#define VSEL_1_85V 0x0 +#define VSEL_2_85V 0x1 +#define VSEL_3_00V 0x2 +#define VSEL_3_15V 0x3 + +//LEDEN register +#define LEDEN 0xEE +#define LEDAON (0x1UL << 0) +#define LEDBON (0x1UL << 1) +#define LEDAPWM (0x1UL << 4) +#define LEDBPWM (0x1UL << 5) + +#endif //__TPS65950_H__ diff --git a/BeagleBoardPkg/InterruptDxe/HardwareInterrupt.c b/BeagleBoardPkg/InterruptDxe/HardwareInterrupt.c new file mode 100644 index 0000000000..97361ffbc1 --- /dev/null +++ b/BeagleBoardPkg/InterruptDxe/HardwareInterrupt.c @@ -0,0 +1,339 @@ +/** @file
+ Template for Metronome 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/Cpu.h>
+#include <Protocol/HardwareInterrupt.h>
+
+#include <Omap3530/Omap3530.h>
+
+//
+// Notifications
+//
+VOID *CpuProtocolNotificationToken = NULL;
+EFI_EVENT CpuProtocolNotificationEvent = (EFI_EVENT)NULL;
+EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
+
+
+HARDWARE_INTERRUPT_HANDLER gRegisteredInterruptHandlers[INT_NROF_VECTORS];
+
+/**
+ Shutdown our hardware
+
+ DXE Core will disable interrupts and turn off the timer and disable interrupts
+ after all the event handlers have run.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+ExitBootServicesEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ // Disable all interrupts
+ MmioWrite32(INTCPS_MIR(0), 0xFFFFFFFF);
+ MmioWrite32(INTCPS_MIR(1), 0xFFFFFFFF);
+ MmioWrite32(INTCPS_MIR(2), 0xFFFFFFFF);
+ MmioWrite32(INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);
+}
+
+/**
+ Register Handler for the specified interrupt source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+ @param Handler Callback for interrupt. NULL to unregister
+
+ @retval EFI_SUCCESS Source was updated to support Handler.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterInterruptSource (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN HARDWARE_INTERRUPT_HANDLER Handler
+ )
+{
+ if (Source > MAX_VECTOR) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gRegisteredInterruptHandlers[Source] = Handler;
+
+ return This->EnableInterruptSource(This, Source);
+}
+
+
+/**
+ Enable interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt enabled.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+EnableInterruptSource (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ )
+{
+ UINTN Bank;
+ UINTN Bit;
+
+ if (Source > MAX_VECTOR) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ Bank = Source / 32;
+ Bit = 1UL << (Source % 32);
+
+ MmioWrite32(INTCPS_MIR_CLEAR(Bank), Bit);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Disable interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt disabled.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableInterruptSource(
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ )
+{
+ UINTN Bank;
+ UINTN Bit;
+
+ if (Source > MAX_VECTOR) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ Bank = Source / 32;
+ Bit = 1UL << (Source % 32);
+
+ MmioWrite32(INTCPS_MIR_SET(Bank), Bit);
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Return current state of interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+ @param InterruptState TRUE: source enabled, FALSE: source disabled.
+
+ @retval EFI_SUCCESS InterruptState is valid
+ @retval EFI_DEVICE_ERROR InterruptState is not valid
+
+**/
+EFI_STATUS
+EFIAPI
+GetInterruptSourceState (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN BOOLEAN *InterruptState
+ )
+{
+ UINTN Bank;
+ UINTN Bit;
+
+ if (InterruptState == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Source > MAX_VECTOR) {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ Bank = Source / 32;
+ Bit = 1UL << (Source % 32);
+
+ if ((MmioRead32(INTCPS_MIR(Bank)) & Bit) == Bit) {
+ *InterruptState = FALSE;
+ } else {
+ *InterruptState = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
+
+ @param InterruptType Defines the type of interrupt or exception that
+ occurred on the processor.This parameter is processor architecture specific.
+ @param SystemContext A pointer to the processor context when
+ the interrupt occurred on the processor.
+
+ @return None
+
+**/
+VOID
+EFIAPI
+IrqInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 Vector;
+ HARDWARE_INTERRUPT_HANDLER InterruptHandler;
+
+ Vector = MmioRead32(INTCPS_SIR_IRQ) & INTCPS_SIR_IRQ_MASK;
+
+ InterruptHandler = gRegisteredInterruptHandlers[Vector];
+ if (InterruptHandler != NULL) {
+ // Call the registered interrupt handler.
+ InterruptHandler(Vector, SystemContext);
+ }
+
+ MmioWrite32(INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);
+}
+
+//
+// Making this global saves a few bytes in image size
+//
+EFI_HANDLE gHardwareInterruptHandle = NULL;
+
+//
+// The protocol instance produced by this driver
+//
+EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = {
+ RegisterInterruptSource,
+ EnableInterruptSource,
+ DisableInterruptSource,
+ GetInterruptSourceState
+};
+
+//
+// Notification routines
+//
+VOID
+CpuProtocolInstalledNotification (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_CPU_ARCH_PROTOCOL *Cpu;
+
+ //
+ // Get the cpu protocol that this driver requires.
+ //
+ Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Unregister the default exception handler.
+ //
+ Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Register to receive interrupts
+ //
+ Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);
+ ASSERT_EFI_ERROR(Status);
+}
+
+/**
+ 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
+InterruptDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ // Make sure the Interrupt Controller Protocol is not already installed in the system.
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
+
+ // Make sure all interrupts are disabled by default.
+ MmioWrite32(INTCPS_MIR(0), 0xFFFFFFFF);
+ MmioWrite32(INTCPS_MIR(1), 0xFFFFFFFF);
+ MmioWrite32(INTCPS_MIR(2), 0xFFFFFFFF);
+ MmioWrite32(INTCPS_CONTROL, INTCPS_CONTROL_NEWIRQAGR);
+
+ Status = gBS->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle,
+ &gHardwareInterruptProtocolGuid, &gHardwareInterruptProtocol,
+ NULL);
+ ASSERT_EFI_ERROR(Status);
+
+ // Set up to be notified when the Cpu protocol is installed.
+ Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CpuProtocolInstalledNotification, NULL, &CpuProtocolNotificationEvent);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = gBS->RegisterProtocolNotify(&gEfiCpuArchProtocolGuid, CpuProtocolNotificationEvent, (VOID *)&CpuProtocolNotificationToken);
+ ASSERT_EFI_ERROR(Status);
+
+ // Register for an ExitBootServicesEvent
+ Status = gBS->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
diff --git a/BeagleBoardPkg/InterruptDxe/InterruptDxe.inf b/BeagleBoardPkg/InterruptDxe/InterruptDxe.inf new file mode 100644 index 0000000000..92b8f780bf --- /dev/null +++ b/BeagleBoardPkg/InterruptDxe/InterruptDxe.inf @@ -0,0 +1,56 @@ +#%HEADER%
+#/** @file
+#
+# Interrupt DXE driver
+#
+# Copyright (c) 2009, 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 = BeagleBoardInterruptDxe
+ FILE_GUID = 23eed05d-1b93-4a1a-8e1b-931d69e37952
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InterruptDxeInitialize
+
+
+[Sources.common]
+ HardwareInterrupt.c
+
+
+[Packages]
+ BeagleBoardPkg/BeagleBoardPkg.dec
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ DebugLib
+ PrintLib
+ UefiDriverEntryPoint
+ IoLib
+
+[Guids]
+
+
+[Protocols]
+ gHardwareInterruptProtocolGuid
+ gEfiCpuArchProtocolGuid
+
+[FixedPcd.common]
+ gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress
+
+[depex]
+ TRUE
diff --git a/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.c b/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.c new file mode 100644 index 0000000000..a03ef575fb --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.c @@ -0,0 +1,110 @@ +/** @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/ArmLib.h> +#include <Library/CacheMaintenanceLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/IoLib.h> +#include <Library/PcdLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/BeagleBoardSystemLib.h> + +#include <Omap3530/Omap3530.h> + +VOID +ResetSystem ( + IN EFI_RESET_TYPE ResetType + ) +{ + switch (ResetType) { + case EfiResetWarm: + //Perform warm reset of the system. + GoLittleEndian(PcdGet32(PcdFlashFvMainBase)); + break; + case EfiResetCold: + case EfiResetShutdown: + default: + //Perform cold reset of the system. + MmioOr32(PRM_RSTCTRL, RST_DPLL3); + while ((MmioRead32(PRM_RSTST) & GLOBAL_COLD_RST) != 0x1); + break; + } + + //Should never come here. + ASSERT(FALSE); +} + +VOID +ShutdownEfi ( + VOID + ) +{ + EFI_STATUS Status; + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + UINTN MapKey; + UINTN DescriptorSize; + UINTN DescriptorVersion; + UINTN Pages; + + MemoryMap = NULL; + MemoryMapSize = 0; + do { + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + + Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1; + MemoryMap = AllocatePages (Pages); + + // + // Get System MemoryMap + // + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + // Don't do anything between the GetMemoryMap() and ExitBootServices() + if (!EFI_ERROR (Status)) { + Status = gBS->ExitBootServices (gImageHandle, MapKey); + if (EFI_ERROR (Status)) { + FreePages (MemoryMap, Pages); + MemoryMap = NULL; + MemoryMapSize = 0; + } + } + } + } while (EFI_ERROR (Status)); + + //Clean and invalidate caches. + WriteBackInvalidateDataCache(); + InvalidateInstructionCache(); + + //Turning off Caches and MMU + ArmDisableDataCache(); + ArmDisableInstructionCache(); + ArmDisableMmu(); +} + diff --git a/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf b/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf new file mode 100644 index 0000000000..2c23ad00e7 --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardSystemLib/BeagleBoardSystemLib.inf @@ -0,0 +1,45 @@ +#%HEADER%
+#/** @file
+# Support for Airport libraries.
+#
+# Copyright (c) 2009, Apple Inc.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BeagleBoardSystemLib
+ FILE_GUID = b15a2640-fef2-447c-98e1-9ce22cfa529c
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BeagleBoardSystemLib
+
+[Sources.ARM]
+ BeagleBoardSystemLib.c
+ GoLittleEndian.asm | RVCT
+ GoLittleEndian.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+ BeagleBoardPkg/BeagleBoardPkg.dec
+
+[LibraryClasses]
+ ArmLib
+ CacheMaintenanceLib
+ MemoryAllocationLib
+ UefiRuntimeServicesTableLib
+ TimerLib
+ UefiLib
+
+[Pcd]
+ gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase
diff --git a/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.S b/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.S new file mode 100644 index 0000000000..a37ae7c883 --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.S @@ -0,0 +1,27 @@ +#------------------------------------------------------------------------------ +# +# 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 3 +.globl ASM_PFX(GoLittleEndian) + +// r0 is target address +ASM_PFX(GoLittleEndian): + + // Switch to SVC Mode + mov r2,#0xD3 // SVC mode + msr CPSR_c,r2 // Switch modes + + bx r0 + diff --git a/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.asm b/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.asm new file mode 100755 index 0000000000..8daced6b8f --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardSystemLib/GoLittleEndian.asm @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +// +// 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 GoLittleEndian + PRESERVE8 + AREA Ebl, CODE, READONLY + +// r0 is target address +GoLittleEndian + // Switch to SVC Mode + mov r2,#0xD3 // SVC mode + msr CPSR_c,r2 // Switch modes + + bx r0 + + END diff --git a/BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf b/BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf new file mode 100644 index 0000000000..5b59014585 --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardTimerLib/BeagleBoardTimerLib.inf @@ -0,0 +1,46 @@ +#%HEADER%
+#/** @file
+# Timer library implementation
+#
+# A non-functional instance of the Timer Library that can be used as a template
+# for the implementation of a functional timer library instance. This library instance can
+# also be used to test build DXE, Runtime, DXE SAL, and DXE SMM modules that require timer
+# services as well as EBC modules that require timer services
+# 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 = BeagleBoardTimerLib
+ FILE_GUID = fe1d7183-9abb-42ce-9a3b-36d7c6a8959f
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TimerLib
+
+[Sources.common]
+ TimerLib.c
+
+[Packages]
+ BeagleBoardPkg/BeagleBoardPkg.dec
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ OmapLib
+ IoLib
+
+[Pcd]
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedPerformanceCounterFreqencyInHz
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds
+ gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer
+
diff --git a/BeagleBoardPkg/Library/BeagleBoardTimerLib/TimerLib.c b/BeagleBoardPkg/Library/BeagleBoardTimerLib/TimerLib.c new file mode 100755 index 0000000000..1b9a5bac4f --- /dev/null +++ b/BeagleBoardPkg/Library/BeagleBoardTimerLib/TimerLib.c @@ -0,0 +1,102 @@ +/** @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 <Base.h>
+
+#include <Library/BaseLib.h>
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/OmapLib.h>
+
+#include <Omap3530/Omap3530.h>
+
+UINTN
+EFIAPI
+MicroSecondDelay (
+ IN UINTN MicroSeconds
+ )
+{
+ UINT64 NanoSeconds;
+
+ NanoSeconds = MultU64x32(MicroSeconds, 1000);
+
+ while (NanoSeconds > (UINTN)-1) {
+ NanoSecondDelay((UINTN)-1);
+ NanoSeconds -= (UINTN)-1;
+ }
+
+ NanoSecondDelay(NanoSeconds);
+
+ return MicroSeconds;
+}
+
+UINTN
+EFIAPI
+NanoSecondDelay (
+ IN UINTN NanoSeconds
+ )
+{
+ UINT32 Delay;
+ UINT32 StartTime;
+ UINT32 CurrentTime;
+ UINT32 ElapsedTime;
+ UINT32 TimerCountRegister;
+
+ Delay = (NanoSeconds / PcdGet32(PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds)) + 1;
+
+ TimerCountRegister = TimerBase(PcdGet32(PcdBeagleFreeTimer)) + GPTIMER_TCRR;
+
+ StartTime = MmioRead32(TimerCountRegister);
+
+ do
+ {
+ CurrentTime = MmioRead32(TimerCountRegister);
+ ElapsedTime = CurrentTime - StartTime;
+ } while (ElapsedTime < Delay);
+
+ NanoSeconds = ElapsedTime * PcdGet32(PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds);
+
+ return NanoSeconds;
+}
+
+UINT64
+EFIAPI
+GetPerformanceCounter (
+ VOID
+ )
+{
+ return (UINT64)MmioRead32(TimerBase(PcdGet32(PcdBeagleFreeTimer)) + GPTIMER_TCRR);
+}
+
+UINT64
+EFIAPI
+GetPerformanceCounterProperties (
+ OUT UINT64 *StartValue, OPTIONAL
+ OUT UINT64 *EndValue OPTIONAL
+ )
+{
+ if (StartValue != NULL) {
+ // Timer starts with the reload value
+ *StartValue = (UINT64)MmioRead32(TimerBase(PcdGet32(PcdBeagleFreeTimer)) + GPTIMER_TLDR);
+ }
+
+ if (EndValue != NULL) {
+ // Timer counts up to 0xFFFFFFFF
+ *EndValue = 0xFFFFFFFF;
+ }
+
+ return PcdGet64(PcdEmbeddedPerformanceCounterFreqencyInHz);
+}
diff --git a/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.c b/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.c new file mode 100644 index 0000000000..93164d68df --- /dev/null +++ b/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.c @@ -0,0 +1,42 @@ +/** @file
+ Add custom commands for BeagleBoard development.
+
+ 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/ArmLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/EblCmdLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/EfiFileLib.h>
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mLibCmdTemplate[] =
+{
+};
+
+
+VOID
+EblInitializeExternalCmd (
+ VOID
+ )
+{
+ EblAddCommands (mLibCmdTemplate, sizeof (mLibCmdTemplate)/sizeof (EBL_COMMAND_TABLE));
+ return;
+}
diff --git a/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf b/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf new file mode 100644 index 0000000000..aa8482b79d --- /dev/null +++ b/BeagleBoardPkg/Library/EblCmdLib/EblCmdLib.inf @@ -0,0 +1,49 @@ +#%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 = BeagleBoardEblCmdLib
+ FILE_GUID = ea62bdc3-1063-425f-8851-98cb47f213a8
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = EblCmdLib|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]
+ EblCmdLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+
+[Protocols]
+
+[Guids]
+
+[Pcd]
diff --git a/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.c b/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.c new file mode 100644 index 0000000000..9d5f429e2d --- /dev/null +++ b/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.c @@ -0,0 +1,103 @@ +/** @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/OmapLib.h> +#include <Omap3530/Omap3530.h> + +RETURN_STATUS +EFIAPI +GdbSerialLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return RETURN_SUCCESS; +} + +RETURN_STATUS +EFIAPI +GdbSerialInit ( + IN UINT64 BaudRate, + IN UINT8 Parity, + IN UINT8 DataBits, + IN UINT8 StopBits + ) +{ + return RETURN_SUCCESS; +} + +BOOLEAN +EFIAPI +GdbIsCharAvailable ( + VOID + ) +{ + UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG; + + if ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_NOT_EMPTY) { + return TRUE; + } else { + return FALSE; + } +} + +CHAR8 +EFIAPI +GdbGetChar ( + VOID + ) +{ + UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG; + UINT32 RBR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_RBR_REG; + CHAR8 Char; + + while ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_EMPTY); + Char = MmioRead8(RBR); + + return Char; +} + +VOID +EFIAPI +GdbPutChar ( + IN CHAR8 Char + ) +{ + UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG; + UINT32 THR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_THR_REG; + + while ((MmioRead8(LSR) & UART_LSR_TX_FIFO_E_MASK) == UART_LSR_TX_FIFO_E_NOT_EMPTY); + MmioWrite8(THR, Char); +} + +VOID +GdbPutString ( + IN CHAR8 *String + ) +{ + while (*String != '\0') { + GdbPutChar (*String); + String++; + } +} + + + + diff --git a/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf b/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf new file mode 100644 index 0000000000..c8e6859023 --- /dev/null +++ b/BeagleBoardPkg/Library/GdbSerialLib/GdbSerialLib.inf @@ -0,0 +1,29 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = GdbSerialLib + FILE_GUID = E2423349-EF5D-439B-95F5-8B8D8E3B443F + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = GdbSerialLib + + CONSTRUCTOR = GdbSerialLibConstructor + + +[Sources.common] + GdbSerialLib.c + + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + DebugLib + IoLib + OmapLib + +[FixedPcd] + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart + diff --git a/BeagleBoardPkg/Library/OmapLib/OmapLib.c b/BeagleBoardPkg/Library/OmapLib/OmapLib.c new file mode 100644 index 0000000000..7464b2e74a --- /dev/null +++ b/BeagleBoardPkg/Library/OmapLib/OmapLib.c @@ -0,0 +1,83 @@ +/** @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 <Base.h>
+#include <Library/DebugLib.h>
+#include <Library/OmapLib.h>
+#include <Omap3530/Omap3530.h>
+
+UINT32
+GpioBase (
+ IN UINTN Port
+ )
+{
+ switch (Port) {
+ case 1: return GPIO1_BASE;
+ case 2: return GPIO2_BASE;
+ case 3: return GPIO3_BASE;
+ case 4: return GPIO4_BASE;
+ case 5: return GPIO5_BASE;
+ case 6: return GPIO6_BASE;
+ default: ASSERT(FALSE); return 0;
+ }
+}
+
+UINT32
+TimerBase (
+ IN UINTN Timer
+ )
+{
+ switch (Timer) {
+ case 1: return GPTIMER1_BASE;
+ case 2: return GPTIMER2_BASE;
+ case 3: return GPTIMER3_BASE;
+ case 4: return GPTIMER4_BASE;
+ case 5: return GPTIMER5_BASE;
+ case 6: return GPTIMER6_BASE;
+ case 7: return GPTIMER7_BASE;
+ case 8: return GPTIMER8_BASE;
+ case 9: return GPTIMER9_BASE;
+ case 10: return GPTIMER10_BASE;
+ case 11: return GPTIMER11_BASE;
+ case 12: return GPTIMER12_BASE;
+ default: return 0;
+ }
+}
+
+UINTN
+InterruptVectorForTimer (
+ IN UINTN Timer
+ )
+{
+ if ((Timer < 1) || (Timer > 12)) {
+ ASSERT(FALSE);
+ return 0xFFFFFFFF;
+ }
+
+ return 36 + Timer;
+}
+
+UINT32
+UartBase (
+ IN UINTN Uart
+ )
+{
+ switch (Uart) {
+ case 1: return UART1_BASE;
+ case 2: return UART2_BASE;
+ case 3: return UART3_BASE;
+ default: ASSERT(FALSE); return 0;
+ }
+}
+
diff --git a/BeagleBoardPkg/Library/OmapLib/OmapLib.inf b/BeagleBoardPkg/Library/OmapLib/OmapLib.inf new file mode 100644 index 0000000000..8fe030cff1 --- /dev/null +++ b/BeagleBoardPkg/Library/OmapLib/OmapLib.inf @@ -0,0 +1,25 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = OmapLib
+ FILE_GUID = d035f5c2-1b92-4746-9f6c-5ff6202970df
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = OmapLib
+
+[Sources.common]
+ OmapLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ BeagleBoardPkg/BeagleBoardPkg.dec
+
+[LibraryClasses]
+ DebugLib
+
+[Protocols]
+
+[Guids]
+
+[Pcd]
diff --git a/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.c b/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.c new file mode 100644 index 0000000000..9c427e5c65 --- /dev/null +++ b/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.c @@ -0,0 +1,84 @@ +/** @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/PcdLib.h>
+#include <Library/ArmLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/EfiResetSystemLib.h>
+
+#include <Library/BeagleBoardSystemLib.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
+ )
+{
+ if (ResetData != NULL) {
+ DEBUG((EFI_D_ERROR, "%s", ResetData));
+ }
+
+ //Shutdown EFI services.
+ ShutdownEfi();
+
+ //Reset the sytem.
+ ResetSystem(ResetType);
+
+ // If the reset didn't work, return an error.
+ 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;
+}
+
diff --git a/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf b/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf new file mode 100644 index 0000000000..e62d94b5b4 --- /dev/null +++ b/BeagleBoardPkg/Library/ResetSystemLib/ResetSystemLib.inf @@ -0,0 +1,41 @@ +#%HEADER%
+#/** @file
+# Reset System lib to make it easy to port new platforms
+#
+# 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 = BeagleBoardResetSystemLib
+ FILE_GUID = 781371a2-3fdd-41d4-96a1-7b34cbc9e895
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = EfiResetSystemLib
+
+
+[Sources.common]
+ ResetSystemLib.c
+
+[Packages]
+ BeagleBoardPkg/BeagleBoardPkg.dec
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[Pcd.common]
+ gArmTokenSpaceGuid.PcdCpuResetAddress
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress
+
+[LibraryClasses]
+ DebugLib
+ BeagleBoardSystemLib
diff --git a/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.c b/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.c new file mode 100644 index 0000000000..0509deb8ab --- /dev/null +++ b/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.c @@ -0,0 +1,124 @@ +/** @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/DebugLib.h>
+#include <Library/SerialPortLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/OmapLib.h>
+#include <Omap3530/Omap3530.h>
+
+/*
+
+ Programmed hardware of Serial port.
+
+ @return Always return EFI_UNSUPPORTED.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerialPortInitialize (
+ VOID
+ )
+{
+ // assume assembly code at reset vector has setup UART
+ return RETURN_SUCCESS;
+}
+
+/**
+ 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
+)
+{
+ UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG;
+ UINT32 THR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_THR_REG;
+ UINTN Count;
+
+ for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
+ while ((MmioRead8(LSR) & UART_LSR_TX_FIFO_E_MASK) == UART_LSR_TX_FIFO_E_NOT_EMPTY);
+ MmioWrite8(THR, *Buffer);
+ }
+
+ return NumberOfBytes;
+}
+
+
+/**
+ 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
+)
+{
+ UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG;
+ UINT32 RBR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_RBR_REG;
+ UINTN Count;
+
+ for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
+ while ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_EMPTY);
+ *Buffer = MmioRead8(RBR);
+ }
+
+ return NumberOfBytes;
+}
+
+
+/**
+ Check to see if any data is avaiable to be read from the debug device.
+
+ @retval EFI_SUCCESS At least one byte of data is avaiable to be read
+ @retval EFI_NOT_READY No data is avaiable to be read
+ @retval EFI_DEVICE_ERROR The serial device is not functioning properly
+
+**/
+BOOLEAN
+EFIAPI
+SerialPortPoll (
+ VOID
+ )
+{
+ UINT32 LSR = UartBase(PcdGet32(PcdBeagleConsoleUart)) + UART_LSR_REG;
+
+ if ((MmioRead8(LSR) & UART_LSR_RX_FIFO_E_MASK) == UART_LSR_RX_FIFO_E_NOT_EMPTY) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
diff --git a/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf b/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf new file mode 100644 index 0000000000..b81bbca657 --- /dev/null +++ b/BeagleBoardPkg/Library/SerialPortLib/SerialPortLib.inf @@ -0,0 +1,44 @@ +#%HEADER%
+#/** @file
+# EDK Serial port lib
+#
+# Copyright (c) 2009, Apple Inc.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BeagleBoardSerialPortLib
+ FILE_GUID = 97546cbd-c0ff-4c48-ab0b-e4f58862acd3
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialPortLib
+
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ SerialPortLib.c
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ OmapLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BeagleBoardPkg/BeagleBoardPkg.dec
+
+[FixedPcd]
+ gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart
+
diff --git a/BeagleBoardPkg/MMCHSDxe/MMCHS.c b/BeagleBoardPkg/MMCHSDxe/MMCHS.c new file mode 100644 index 0000000000..77c5fbdbfa --- /dev/null +++ b/BeagleBoardPkg/MMCHSDxe/MMCHS.c @@ -0,0 +1,1018 @@ +/** @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 "MMCHS.h" + +EFI_BLOCK_IO_MEDIA MMCHSMedia = { + SIGNATURE_32('s','d','i','o'), // MediaId + FALSE, // RemovableMedia + TRUE, // MediaPresent + TRUE, // LogicalPartition + FALSE, // ReadOnly + FALSE, // WriteCaching + 512, // BlockSize + 4, // IoAlign + 0, // Pad + 0 // LastBlock +}; + +typedef struct { + VENDOR_DEVICE_PATH Mmc; + EFI_DEVICE_PATH End; +} MMCHS_DEVICE_PATH; + +MMCHS_DEVICE_PATH gMmcHsDevicePath = +{ + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8)(sizeof(VENDOR_DEVICE_PATH)), + (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8), + 0xb615f1f5, 0x5088, 0x43cd, 0x80, 0x9c, 0xa1, 0x6e, 0x52, 0x48, 0x7d, 0x00 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + sizeof (EFI_DEVICE_PATH_PROTOCOL), + 0 + } +}; + +CARD_INFO *gCardInfo; +EMBEDDED_EXTERNAL_DEVICE *gTPS65950; + +// +// Internal Functions +// + +STATIC +VOID +ParseCardCIDData ( + UINT32 Response0, + UINT32 Response1, + UINT32 Response2, + UINT32 Response3 + ) +{ + gCardInfo->CIDData.MDT = ((Response0 >> 8) & 0xFFF); + gCardInfo->CIDData.PSN = (((Response0 >> 24) & 0xFF) | ((Response1 & 0xFFFFFF) << 8)); + gCardInfo->CIDData.PRV = ((Response1 >> 24) & 0xFF); + gCardInfo->CIDData.PNM[4] = ((Response2) & 0xFF); + gCardInfo->CIDData.PNM[3] = ((Response2 >> 8) & 0xFF); + gCardInfo->CIDData.PNM[2] = ((Response2 >> 16) & 0xFF); + gCardInfo->CIDData.PNM[1] = ((Response2 >> 24) & 0xFF); + gCardInfo->CIDData.PNM[0] = ((Response3) & 0xFF); + gCardInfo->CIDData.OID = ((Response3 >> 8) & 0xFFFF); + gCardInfo->CIDData.MID = ((Response3 >> 24) & 0xFF); +} + +STATIC +VOID +UpdateMMCHSClkFrequency ( + UINTN NewCLKD + ) +{ + //Set Clock enable to 0x0 to not provide the clock to the card + MmioAnd32(MMCHS_SYSCTL, ~CEN); + + //Set new clock frequency. + MmioAndThenOr32(MMCHS_SYSCTL, ~CLKD_MASK, NewCLKD << 6); + + //Poll till Internal Clock Stable + while ((MmioRead32(MMCHS_SYSCTL) & ICS_MASK) != ICS); + + //Set Clock enable to 0x1 to provide the clock to the card + MmioOr32(MMCHS_SYSCTL, CEN); +} + +STATIC +EFI_STATUS +SendCmd ( + UINTN Cmd, + UINTN CmdInterruptEnableVal, + UINTN CmdArgument + ) +{ + UINTN MmcStatus; + UINTN RetryCount = 0; + + //Check if command line is in use or not. Poll till command line is available. + while ((MmioRead32(MMCHS_PSTATE) & DATI_MASK) == DATI_NOT_ALLOWED); + + //Provide the block size. + MmioWrite32(MMCHS_BLK, BLEN_512BYTES); + + //Setting Data timeout counter value to max value. + MmioAndThenOr32(MMCHS_SYSCTL, ~DTO_MASK, DTO_VAL); + + //Clear Status register. + MmioWrite32(MMCHS_STAT, 0xFFFFFFFF); + + //Set command argument register + MmioWrite32(MMCHS_ARG, CmdArgument); + + //Enable interrupt enable events to occur + MmioWrite32(MMCHS_IE, CmdInterruptEnableVal); + + //Send a command + MmioWrite32(MMCHS_CMD, Cmd); + + //Check for the command status. + while (RetryCount < MAX_RETRY_COUNT) { + do { + MmcStatus = MmioRead32(MMCHS_STAT); + } while (MmcStatus == 0); + + //Read status of command response + if ((MmcStatus & ERRI) != 0) { + + //Perform soft-reset for mmci_cmd line. + MmioOr32(MMCHS_SYSCTL, SRC); + while ((MmioRead32(MMCHS_SYSCTL) & SRC)); + + DEBUG ((EFI_D_INFO, "MmcStatus: %x\n", MmcStatus)); + return EFI_DEVICE_ERROR; + } + + //Check if command is completed. + if ((MmcStatus & CC) == CC) { + MmioWrite32(MMCHS_STAT, CC); + break; + } + + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +VOID +GetBlockInformation ( + UINTN *BlockSize, + UINTN *NumBlocks + ) +{ + CSD_SDV2 *CsdSDV2Data; + UINTN CardSize; + + if (gCardInfo->CardType == SD_CARD_2_HIGH) { + CsdSDV2Data = (CSD_SDV2 *)&gCardInfo->CSDData; + + //Populate BlockSize. + *BlockSize = (0x1UL << CsdSDV2Data->READ_BL_LEN); + + //Calculate Total number of blocks. + CardSize = CsdSDV2Data->C_SIZELow16 | (CsdSDV2Data->C_SIZEHigh6 << 2); + *NumBlocks = ((CardSize + 1) * 1024); + } else { + //Populate BlockSize. + *BlockSize = (0x1UL << gCardInfo->CSDData.READ_BL_LEN); + + //Calculate Total number of blocks. + CardSize = gCardInfo->CSDData.C_SIZELow2 | (gCardInfo->CSDData.C_SIZEHigh10 << 2); + *NumBlocks = (CardSize + 1) * (1 << (gCardInfo->CSDData.C_SIZE_MULT + 2)); + } + + //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes. + if (*BlockSize > 512) { + *NumBlocks = MultU64x32(*NumBlocks, *BlockSize/2); + *BlockSize = 512; + } + + DEBUG ((EFI_D_INFO, "Card type: %x, BlockSize: %x, NumBlocks: %x\n", gCardInfo->CardType, *BlockSize, *NumBlocks)); +} + +STATIC +VOID +CalculateCardCLKD ( + UINTN *ClockFrequencySelect + ) +{ + UINT8 MaxDataTransferRate; + UINTN TransferRateValue = 0; + UINTN TimeValue = 0 ; + UINTN Frequency = 0; + + MaxDataTransferRate = gCardInfo->CSDData.TRAN_SPEED; + + //Calculate Transfer rate unit (Bits 2:0 of TRAN_SPEED) + switch (MaxDataTransferRate & 0x7) { + case 0: + TransferRateValue = 100 * 1000; + break; + + case 1: + TransferRateValue = 1 * 1000 * 1000; + break; + + case 2: + TransferRateValue = 10 * 1000 * 1000; + break; + + case 3: + TransferRateValue = 100 * 1000 * 1000; + break; + + default: + DEBUG((EFI_D_ERROR, "Invalid parameter.\n")); + ASSERT(FALSE); + } + + //Calculate Time value (Bits 6:3 of TRAN_SPEED) + switch ((MaxDataTransferRate >> 3) & 0xF) { + case 1: + TimeValue = 10; + break; + + case 2: + TimeValue = 12; + break; + + case 3: + TimeValue = 13; + break; + + case 4: + TimeValue = 15; + break; + + case 5: + TimeValue = 20; + break; + + case 6: + TimeValue = 25; + break; + + case 7: + TimeValue = 30; + break; + + case 8: + TimeValue = 35; + break; + + case 9: + TimeValue = 40; + break; + + case 10: + TimeValue = 45; + break; + + case 11: + TimeValue = 50; + break; + + case 12: + TimeValue = 55; + break; + + case 13: + TimeValue = 60; + break; + + case 14: + TimeValue = 70; + break; + + case 15: + TimeValue = 80; + break; + + default: + DEBUG((EFI_D_ERROR, "Invalid parameter.\n")); + ASSERT(FALSE); + } + + Frequency = TransferRateValue * TimeValue/10; + + //Calculate Clock divider value to program in MMCHS_SYSCTL[CLKD] field. + *ClockFrequencySelect = ((MMC_REFERENCE_CLK/Frequency) + 1); + + DEBUG ((EFI_D_INFO, "MaxDataTransferRate: 0x%x, Frequency: %d KHz, ClockFrequencySelect: %x\n", MaxDataTransferRate, Frequency/1000, *ClockFrequencySelect)); +} + +STATIC +VOID +GetCardConfigurationData ( + VOID + ) +{ + UINTN BlockSize; + UINTN NumBlocks; + UINTN ClockFrequencySelect; + + //Calculate BlockSize and Total number of blocks in the detected card. + GetBlockInformation(&BlockSize, &NumBlocks); + gCardInfo->BlockSize = BlockSize; + gCardInfo->NumBlocks = NumBlocks; + + //Calculate Card clock divider value. + CalculateCardCLKD(&ClockFrequencySelect); + gCardInfo->ClockFrequencySelect = ClockFrequencySelect; +} + +STATIC +EFI_STATUS +InitializeMMCHS ( + VOID + ) +{ + UINT8 Data = 0; + EFI_STATUS Status; + + //Select Device group to belong to P1 device group in Power IC. + Data = DEV_GRP_P1; + Status = gTPS65950->Write(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEV_GRP), 1, &Data); + ASSERT_EFI_ERROR(Status); + + //Configure voltage regulator for MMC1 in Power IC to output 3.0 voltage. + Data = VSEL_3_00V; + Status = gTPS65950->Write(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID4, VMMC1_DEDICATED_REG), 1, &Data); + ASSERT_EFI_ERROR(Status); + + //After ramping up voltage, set VDDS stable bit to indicate that voltage level is stable. + MmioOr32(CONTROL_PBIAS_LITE, (PBIASLITEVMODE0 | PBIASLITEPWRDNZ0 | PBIASSPEEDCTRL0 | PBIASLITEVMODE1 | PBIASLITEWRDNZ1)); + + //Software reset of the MMCHS host controller. + MmioWrite32(MMCHS_SYSCONFIG, SOFTRESET); + gBS->Stall(1000); + while ((MmioRead32(MMCHS_SYSSTATUS) & RESETDONE_MASK) != RESETDONE); + + //Soft reset for all. + MmioWrite32(MMCHS_SYSCTL, SRA); + gBS->Stall(1000); + while ((MmioRead32(MMCHS_SYSCTL) & SRA) != 0x0); + + //Voltage capabilities initialization. Activate VS18 and VS30. + MmioOr32(MMCHS_CAPA, (VS30 | VS18)); + + //Wakeup configuration + MmioOr32(MMCHS_SYSCONFIG, ENAWAKEUP); + MmioOr32(MMCHS_HCTL, IWE); + + //MMCHS Controller default initialization + MmioOr32(MMCHS_CON, (OD | DW8_1_4_BIT | CEATA_OFF)); + + MmioWrite32(MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_OFF)); + + //Enable internal clock + MmioOr32(MMCHS_SYSCTL, ICE); + + //Set the clock frequency to 80KHz. + UpdateMMCHSClkFrequency(CLKD_80KHZ); + + //Enable SD bus power. + MmioOr32(MMCHS_HCTL, (SDBP_ON)); + + //Poll till SD bus power bit is set. + while ((MmioRead32(MMCHS_HCTL) & SDBP_MASK) != SDBP_ON); + + return Status; +} + +STATIC +EFI_STATUS +PerformCardIdenfication ( + VOID + ) +{ + EFI_STATUS Status; + UINTN CmdArgument = 0; + UINTN Response = 0; + UINTN RetryCount = 0; + BOOLEAN SDCmd8Supported = FALSE; + + //Enable interrupts. + MmioWrite32(MMCHS_IE, (BADA_EN | CERR_EN | DEB_EN | DCRC_EN | DTO_EN | CIE_EN | + CEB_EN | CCRC_EN | CTO_EN | BRR_EN | BWR_EN | TC_EN | CC_EN)); + + //Controller INIT procedure start. + MmioOr32(MMCHS_CON, INIT); + MmioWrite32(MMCHS_CMD, 0x00000000); + while (!(MmioRead32(MMCHS_STAT) & CC)); + + //Wait for 1 ms + gBS->Stall(1000); + + //Set CC bit to 0x1 to clear the flag + MmioOr32(MMCHS_STAT, CC); + + //Retry INIT procedure. + MmioWrite32(MMCHS_CMD, 0x00000000); + while (!(MmioRead32(MMCHS_STAT) & CC)); + + //End initialization sequence + MmioAnd32(MMCHS_CON, ~INIT); + + MmioOr32(MMCHS_HCTL, (SDVS_3_0_V | DTW_1_BIT | SDBP_ON)); + + //Change clock frequency to 400KHz to fit protocol + UpdateMMCHSClkFrequency(CLKD_400KHZ); + + MmioOr32(MMCHS_CON, OD); + + //Send CMD0 command. + Status = SendCmd(CMD0, CMD0_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Cmd0 fails.\n")); + return Status; + } + + DEBUG ((EFI_D_INFO, "CMD0 response: %x\n", MmioRead32(MMCHS_RSP10))); + + //Send CMD5 command. + Status = SendCmd(CMD5, CMD5_INT_EN, CmdArgument); + if (Status == EFI_SUCCESS) { + DEBUG ((EFI_D_ERROR, "CMD5 Success. SDIO card. Follow SDIO card specification.\n")); + DEBUG ((EFI_D_INFO, "CMD5 response: %x\n", MmioRead32(MMCHS_RSP10))); + //NOTE: Returning unsupported error for now. Need to implement SDIO specification. + return EFI_UNSUPPORTED; + } else { + DEBUG ((EFI_D_INFO, "CMD5 fails. Not an SDIO card.\n")); + } + + MmioOr32(MMCHS_SYSCTL, SRC); + gBS->Stall(1000); + while ((MmioRead32(MMCHS_SYSCTL) & SRC)); + + //Send CMD8 command. (New v2.00 command for Voltage check) + //Only 2.7V - 3.6V is supported for SD2.0, only SD 2.0 card can pass. + //MMC & SD1.1 card will fail this command. + CmdArgument = CMD8_ARG; + Status = SendCmd(CMD8, CMD8_INT_EN, CmdArgument); + if (Status == EFI_SUCCESS) { + Response = MmioRead32(MMCHS_RSP10); + DEBUG ((EFI_D_INFO, "CMD8 success. CMD8 response: %x\n", Response)); + if (Response != CmdArgument) { + return EFI_DEVICE_ERROR; + } + DEBUG ((EFI_D_INFO, "Card is SD2.0\n")); + SDCmd8Supported = TRUE; //Supports high capacity. + } else { + DEBUG ((EFI_D_INFO, "CMD8 fails. Not an SD2.0 card.\n")); + } + + MmioOr32(MMCHS_SYSCTL, SRC); + gBS->Stall(1000); + while ((MmioRead32(MMCHS_SYSCTL) & SRC)); + + //Poll till card is busy + while (RetryCount < MAX_RETRY_COUNT) { + //Send CMD55 command. + CmdArgument = 0; + Status = SendCmd(CMD55, CMD55_INT_EN, CmdArgument); + if (Status == EFI_SUCCESS) { + DEBUG ((EFI_D_INFO, "CMD55 success. CMD55 response: %x\n", MmioRead32(MMCHS_RSP10))); + gCardInfo->CardType = SD_CARD; + } else { + DEBUG ((EFI_D_INFO, "CMD55 fails.\n")); + gCardInfo->CardType = MMC_CARD; + } + + //Send appropriate command for the card type which got detected. + if (gCardInfo->CardType == SD_CARD) { + CmdArgument = ((UINTN *) &(gCardInfo->OCRData))[0]; + + //Set HCS bit. + if (SDCmd8Supported) { + CmdArgument |= HCS; + } + + Status = SendCmd(ACMD41, ACMD41_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_INFO, "ACMD41 fails.\n")); + return Status; + } + ((UINT32 *) &(gCardInfo->OCRData))[0] = MmioRead32(MMCHS_RSP10); + DEBUG ((EFI_D_INFO, "SD card detected. ACMD41 OCR: %x\n", ((UINT32 *) &(gCardInfo->OCRData))[0])); + } else if (gCardInfo->CardType == MMC_CARD) { + CmdArgument = 0; + Status = SendCmd(CMD1, CMD1_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_INFO, "CMD1 fails.\n")); + return Status; + } + Response = MmioRead32(MMCHS_RSP10); + DEBUG ((EFI_D_INFO, "MMC card detected.. CMD1 response: %x\n", Response)); + + //NOTE: For now, I am skipping this since I only have an SD card. + //Compare card OCR and host OCR (Section 22.6.1.3.2.4) + return EFI_UNSUPPORTED; //For now, MMC is not supported. + } + + //Poll the card until it is out of its power-up sequence. + if (gCardInfo->OCRData.Busy == 1) { + + if (SDCmd8Supported) { + gCardInfo->CardType = SD_CARD_2; + } + + //Card is ready. Check CCS (Card capacity status) bit (bit#30). + //SD 2.0 standard card will response with CCS 0, SD high capacity card will respond with CCS 1. + if (gCardInfo->OCRData.AccessMode & BIT1) { + gCardInfo->CardType = SD_CARD_2_HIGH; + DEBUG ((EFI_D_INFO, "High capacity card.\n")); + } else { + DEBUG ((EFI_D_INFO, "Standard capacity card.\n")); + } + + break; + } + + gBS->Stall(1000); + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + DEBUG ((EFI_D_ERROR, "Timeout error. RetryCount: %d\n", RetryCount)); + return EFI_TIMEOUT; + } + + //Read CID data. + CmdArgument = 0; + Status = SendCmd(CMD2, CMD2_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD2 fails. Status: %x\n", Status)); + return Status; + } + + DEBUG ((EFI_D_INFO, "CMD2 response: %x %x %x %x\n", MmioRead32(MMCHS_RSP10), MmioRead32(MMCHS_RSP32), MmioRead32(MMCHS_RSP54), MmioRead32(MMCHS_RSP76))); + + //Parse CID register data. + ParseCardCIDData(MmioRead32(MMCHS_RSP10), MmioRead32(MMCHS_RSP32), MmioRead32(MMCHS_RSP54), MmioRead32(MMCHS_RSP76)); + + //Read RCA + CmdArgument = 0; + Status = SendCmd(CMD3, CMD3_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD3 fails. Status: %x\n", Status)); + return Status; + } + + //Set RCA for the detected card. RCA is CMD3 response. + gCardInfo->RCA = (MmioRead32(MMCHS_RSP10) >> 16); + DEBUG ((EFI_D_INFO, "CMD3 response: RCA %x\n", gCardInfo->RCA)); + + //MMC Bus setting change after card identification. + MmioAnd32(MMCHS_CON, ~OD); + MmioOr32(MMCHS_HCTL, SDVS_3_0_V); + UpdateMMCHSClkFrequency(CLKD_400KHZ); //Set the clock frequency to 400KHz. + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetCardSpecificData ( + VOID + ) +{ + EFI_STATUS Status; + UINTN CmdArgument; + + //Send CMD9 to retrieve CSD. + CmdArgument = gCardInfo->RCA << 16; + Status = SendCmd(CMD9, CMD9_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD9 fails. Status: %x\n", Status)); + return Status; + } + + //Populate 128-bit CSD register data. + ((UINT32 *)&(gCardInfo->CSDData))[0] = MmioRead32(MMCHS_RSP10); + ((UINT32 *)&(gCardInfo->CSDData))[1] = MmioRead32(MMCHS_RSP32); + ((UINT32 *)&(gCardInfo->CSDData))[2] = MmioRead32(MMCHS_RSP54); + ((UINT32 *)&(gCardInfo->CSDData))[3] = MmioRead32(MMCHS_RSP76); + + DEBUG ((EFI_D_INFO, "CMD9 response: %x %x %x %x\n", MmioRead32(MMCHS_RSP10), MmioRead32(MMCHS_RSP32), MmioRead32(MMCHS_RSP54), MmioRead32(MMCHS_RSP76))); + + //Calculate total number of blocks and max. data transfer rate supported by the detected card. + GetCardConfigurationData(); + + //Change MMCHS clock frequency to what detected card can support. + UpdateMMCHSClkFrequency(gCardInfo->ClockFrequencySelect); + + return Status; +} + +STATIC +EFI_STATUS +PerformCardConfiguration ( + VOID + ) +{ + UINTN CmdArgument = 0; + EFI_STATUS Status; + + //Send CMD7 + CmdArgument = gCardInfo->RCA << 16; + Status = SendCmd(CMD7, CMD7_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD7 fails. Status: %x\n", Status)); + return Status; + } + + //Send CMD16 to set the block length + CmdArgument = gCardInfo->BlockSize; + Status = SendCmd(CMD16, CMD16_INT_EN, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD16 fails. Status: %x\n", Status)); + return Status; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ReadBlockData( + IN EFI_BLOCK_IO_PROTOCOL *This, + OUT VOID *Buffer + ) +{ + UINTN MmcStatus; + UINTN *DataBuffer = Buffer; + UINTN DataSize = This->Media->BlockSize/4; + UINTN Count; + UINTN RetryCount = 0; + + //Check controller status to make sure there is no error. + while (RetryCount < MAX_RETRY_COUNT) { + do { + //Read Status. + MmcStatus = MmioRead32(MMCHS_STAT); + } while(MmcStatus == 0); + + //Check if Buffer read ready (BRR) bit is set? + if (MmcStatus & BRR) { + + //Clear BRR bit + MmioOr32(MMCHS_STAT, BRR); + + //Read block worth of data. + for (Count = 0; Count < DataSize; Count++) { + *DataBuffer++ = MmioRead32(MMCHS_DATA); + } + break; + } + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +WriteBlockData( + IN EFI_BLOCK_IO_PROTOCOL *This, + OUT VOID *Buffer + ) +{ + UINTN MmcStatus; + UINTN *DataBuffer = Buffer; + UINTN DataSize = This->Media->BlockSize/4; + UINTN Count; + UINTN RetryCount = 0; + + //Check controller status to make sure there is no error. + while (RetryCount < MAX_RETRY_COUNT) { + do { + //Read Status. + MmcStatus = MmioRead32(MMCHS_STAT); + } while(MmcStatus == 0); + + //Check if Buffer write ready (BWR) bit is set? + if (MmcStatus & BWR) { + + //Clear BWR bit + MmioOr32(MMCHS_STAT, BWR); + + //Write block worth of data. + for (Count = 0; Count < DataSize; Count++) { + MmioWrite32(MMCHS_DATA, *DataBuffer++); + } + + break; + } + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +TransferBlockData( + IN EFI_BLOCK_IO_PROTOCOL *This, + OUT VOID *Buffer, + IN OPERATION_TYPE OperationType + ) +{ + EFI_STATUS Status; + UINTN MmcStatus; + UINTN RetryCount = 0; + + //Read or Write data. + if (OperationType == READ) { + Status = ReadBlockData(This, Buffer); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "ReadBlockData fails.\n")); + return Status; + } + } else if (OperationType == WRITE) { + Status = WriteBlockData(This, Buffer); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "WriteBlockData fails.\n")); + return Status; + } + } + + //Check for the Transfer completion. + while (RetryCount < MAX_RETRY_COUNT) { + //Read Status + do { + MmcStatus = MmioRead32(MMCHS_STAT); + } while (MmcStatus == 0); + + //Check if Transfer complete (TC) bit is set? + if (MmcStatus & TC) { + break; + } else { + DEBUG ((EFI_D_ERROR, "MmcStatus for TC: %x\n", MmcStatus)); + //Check if DEB, DCRC or DTO interrupt occured. + if ((MmcStatus & DEB) | (MmcStatus & DCRC) | (MmcStatus & DTO)) { + //There was an error during the data transfer. + + //Set SRD bit to 1 and wait until it return to 0x0. + MmioOr32(MMCHS_SYSCTL, SRD); + while((MmioRead32(MMCHS_SYSCTL) & SRD) != 0x0); + + return EFI_DEVICE_ERROR; + } + } + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + DEBUG ((EFI_D_ERROR, "TransferBlockData timed out.\n")); + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SdReadWrite ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINTN Lba, + OUT VOID *Buffer, + IN UINTN BufferSize, + IN OPERATION_TYPE OperationType + ) +{ + EFI_STATUS Status; + UINTN RetryCount = 0; + UINTN NumBlocks; + UINTN Cmd = 0; + UINTN CmdInterruptEnable = 0; + UINTN CmdArgument = 0; + + //Check if the data lines are not in use. + while ((RetryCount++ < MAX_RETRY_COUNT) && ((MmioRead32(MMCHS_PSTATE) & DATI_MASK) != DATI_ALLOWED)); + if (RetryCount == MAX_RETRY_COUNT) { + return EFI_TIMEOUT; + } + + //Populate the command information based on the operation type. + if (OperationType == READ) { + Cmd = CMD17; //Single block read + CmdInterruptEnable = CMD17_INT_EN; + } else if (OperationType == WRITE) { + Cmd = CMD24; //Single block write + CmdInterruptEnable = CMD24_INT_EN; + } + + //Calculate total number of blocks its going to read. + NumBlocks = (BufferSize + (This->Media->BlockSize - 1))/This->Media->BlockSize; + + //Set command argument based on the card access mode (Byte mode or Block mode) + if (gCardInfo->OCRData.AccessMode & BIT1) { + CmdArgument = (UINTN)Lba; + } else { + CmdArgument = (UINTN)Lba * This->Media->BlockSize; + } + + while(NumBlocks) { + //Send Command. + Status = SendCmd(Cmd, CmdInterruptEnable, CmdArgument); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "CMD fails. Status: %x\n", Status)); + return Status; + } + + //Transfer a block worth of data. + Status = TransferBlockData(This, Buffer, OperationType); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "TransferBlockData fails. %x\n", Status)); + return Status; + } + + //Adjust command argument. + if (gCardInfo->OCRData.AccessMode & BIT1) { + CmdArgument++; //Increase BlockIndex by one. + } else { + CmdArgument += This->Media->BlockSize; //Increase BlockIndex by BlockSize + } + + //Adjust Buffer. + Buffer = (UINT8 *)Buffer + This->Media->BlockSize; + NumBlocks--; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +MMCHSReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +MMCHSReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + + if (Buffer == NULL) + { + return EFI_INVALID_PARAMETER; + } + + if (Lba > This->Media->LastBlock) + { + return EFI_INVALID_PARAMETER; + } + + if ((BufferSize % This->Media->BlockSize) != 0) + { + return EFI_BAD_BUFFER_SIZE; + } + + //Perform Read operation. + Status = SdReadWrite(This, (UINTN)Lba, Buffer, BufferSize, READ); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Read operation fails.\n")); + } + + return Status; +} + +EFI_STATUS +EFIAPI +MMCHSWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Lba > This->Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((BufferSize % This->Media->BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (This->Media->ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + //Perform write operation. + Status = SdReadWrite(This, (UINTN)Lba, Buffer, BufferSize, WRITE); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Write operation fails.\n")); + } + + return Status; +} + +EFI_STATUS +EFIAPI +MMCHSFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +EFI_BLOCK_IO_PROTOCOL BlockIo = +{ + EFI_BLOCK_IO_INTERFACE_REVISION, // Revision + &MMCHSMedia, // *Media + MMCHSReset, // Reset + MMCHSReadBlocks, // ReadBlocks + MMCHSWriteBlocks, // WriteBlocks + MMCHSFlushBlocks // FlushBlocks +}; + +EFI_STATUS +MMCHSInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950); + ASSERT_EFI_ERROR(Status); + + gCardInfo = (CARD_INFO *)AllocateZeroPool(sizeof(CARD_INFO)); + if (gCardInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + //Initialize MMC host controller. + Status = InitializeMMCHS(); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "Initialize MMC host controller fails. Status: %x\n", Status)); + return Status; + } + + //Card idenfication + Status = PerformCardIdenfication(); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "No MMC/SD card detected.\n")); + return EFI_SUCCESS; //NOTE: Check if this is correct.. + } + + //Get CSD (Card specific data) for the detected card. + Status = GetCardSpecificData(); + if (EFI_ERROR(Status)) { + return Status; + } + + //Configure the card in data transfer mode. + Status = PerformCardConfiguration(); + if (EFI_ERROR(Status)) { + return Status; + } + + //Patch the Media structure. + MMCHSMedia.LastBlock = (gCardInfo->NumBlocks - 1); + MMCHSMedia.BlockSize = gCardInfo->BlockSize; + + //Publish BlockIO. + Status = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, + &gEfiBlockIoProtocolGuid, &BlockIo, + &gEfiDevicePathProtocolGuid, &gMmcHsDevicePath, + NULL); + return Status; +} diff --git a/BeagleBoardPkg/MMCHSDxe/MMCHS.h b/BeagleBoardPkg/MMCHSDxe/MMCHS.h new file mode 100755 index 0000000000..9baac74931 --- /dev/null +++ b/BeagleBoardPkg/MMCHSDxe/MMCHS.h @@ -0,0 +1,158 @@ +/** @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 _MMCHS_H_
+#define _MMCHS_H_
+
+#include <Library/BaseLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/PcdLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/EmbeddedExternalDevice.h>
+#include <Protocol/BlockIo.h> +#include <Protocol/Cpu.h> +#include <Protocol/DevicePath.h> + +#include <Omap3530/Omap3530.h>
+#include <TPS65950.h>
+
+#define MAX_RETRY_COUNT 100 + +#define HCS (0x1UL << 30) //Host capacity support/1 = Supporting high capacity
+#define CCS (0x1UL << 30) //Card capacity status/1 = High capacity card
+typedef struct {
+ UINT32 Reserved0: 7; // 0
+ UINT32 V170_V195: 1; // 1.70V - 1.95V
+ UINT32 V200_V260: 7; // 2.00V - 2.60V
+ UINT32 V270_V360: 9; // 2.70V - 3.60V
+ UINT32 RESERVED_1: 5; // Reserved
+ UINT32 AccessMode: 2; // 00b (byte mode), 10b (sector mode)
+ UINT32 Busy: 1; // This bit is set to LOW if the card has not finished the power up routine
+}OCR;
+
+typedef struct {
+ UINT32 NOT_USED; // 1 [0:0]
+ UINT32 CRC; // CRC7 checksum [7:1]
+ UINT32 MDT; // Manufacturing date [19:8]
+ UINT32 RESERVED_1; // Reserved [23:20]
+ UINT32 PSN; // Product serial number [55:24]
+ UINT8 PRV; // Product revision [63:56]
+ UINT8 PNM[5]; // Product name [64:103]
+ UINT16 OID; // OEM/Application ID [119:104]
+ UINT8 MID; // Manufacturer ID [127:120]
+}CID;
+
+typedef struct {
+ UINT8 NOT_USED: 1; // Not used, always 1 [0:0]
+ UINT8 CRC: 7; // CRC [7:1]
+ UINT8 RESERVED_1: 2; // Reserved [9:8]
+ UINT8 FILE_FORMAT: 2; // File format [11:10]
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]
+ UINT16 RESERVED_2: 5; // Reserved [20:16]
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]
+ UINT16 RESERVED_3: 2; // Reserved [30:29]
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]
+ UINT32 WP_GRP_SIZE: 7; // Write protect group size [38:32]
+ UINT32 SECTOR_SIZE: 7; // Erase sector size [45:39]
+ UINT32 ERASE_BLK_EN: 1; // Erase single block enable [46:46]
+ UINT32 C_SIZE_MULT: 3; // Device size multiplier [49:47]
+ UINT32 VDD_W_CURR_MAX: 3; // Max. write current @ VDD max [52:50]
+ UINT32 VDD_W_CURR_MIN: 3; // Max. write current @ VDD min [55:53]
+ UINT32 VDD_R_CURR_MAX: 3; // Max. read current @ VDD max [58:56]
+ UINT32 VDD_R_CURR_MIN: 3; // Max. read current @ VDD min [61:59]
+ UINT32 C_SIZELow2: 2; // Device size [73:62]
+ UINT32 C_SIZEHigh10: 10;// Device size [73:62]
+ UINT32 RESERVED_4: 2; // Reserved [75:74]
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]
+ UINT32 READ_BL_LEN: 4; // Max. read data block length [83:80]
+ UINT32 CCC: 12;// Card command classes [95:84]
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+ UINT8 TAAC ; // Data read access-time 1 [119:112]
+ UINT8 RESERVED_5: 6; // Reserved [125:120]
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
+}CSD;
+
+typedef struct {
+ UINT8 NOT_USED: 1; // Not used, always 1 [0:0]
+ UINT8 CRC: 7; // CRC [7:1]
+ UINT8 RESERVED_1: 2; // Reserved [9:8]
+ UINT8 FILE_FORMAT: 2; // File format [11:10]
+ UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12]
+ UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13]
+ UINT8 COPY: 1; // Copy flag (OTP) [14:14]
+ UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15]
+ UINT16 RESERVED_2: 5; // Reserved [20:16]
+ UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21]
+ UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22]
+ UINT16 R2W_FACTOR: 3; // Write speed factor [28:26]
+ UINT16 RESERVED_3: 2; // Reserved [30:29]
+ UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31]
+ UINT16 WP_GRP_SIZE: 7; // Write protect group size [38:32]
+ UINT16 SECTOR_SIZE: 7; // Erase sector size [45:39]
+ UINT16 ERASE_BLK_EN: 1; // Erase single block enable [46:46]
+ UINT16 RESERVED_4: 1; // Reserved [47:47]
+ UINT32 C_SIZELow16: 16;// Device size [69:48]
+ UINT32 C_SIZEHigh6: 6; // Device size [69:48]
+ UINT32 RESERVED_5: 6; // Reserved [75:70]
+ UINT32 DSR_IMP: 1; // DSR implemented [76:76]
+ UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77]
+ UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78]
+ UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79]
+ UINT16 READ_BL_LEN: 4; // Max. read data block length [83:80]
+ UINT16 CCC: 12;// Card command classes [95:84]
+ UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96]
+ UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104]
+ UINT8 TAAC ; // Data read access-time 1 [119:112]
+ UINT8 RESERVED_6: 6; // 0 [125:120]
+ UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126]
+}CSD_SDV2;
+
+typedef enum { + UNKNOWN_CARD, + MMC_CARD, //MMC card + SD_CARD, //SD 1.1 card + SD_CARD_2, //SD 2.0 or above standard card + SD_CARD_2_HIGH //SD 2.0 or above high capacity card +} CARD_TYPE;
+
+typedef enum {
+ READ,
+ WRITE
+} OPERATION_TYPE;
+
+typedef struct
+{
+ UINT16 RCA;
+ UINTN BlockSize;
+ UINTN NumBlocks;
+ UINTN ClockFrequencySelect;
+ CARD_TYPE CardType;
+ OCR OCRData;
+ CID CIDData;
+ CSD CSDData;
+} CARD_INFO;
+
+#endif
diff --git a/BeagleBoardPkg/MMCHSDxe/MMCHS.inf b/BeagleBoardPkg/MMCHSDxe/MMCHS.inf new file mode 100644 index 0000000000..3636f35583 --- /dev/null +++ b/BeagleBoardPkg/MMCHSDxe/MMCHS.inf @@ -0,0 +1,39 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MMCHS + FILE_GUID = 100c2cfa-b586-4198-9b4c-1683d195b1da + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = MMCHSInitialize + + +[Sources.common] + MMCHS.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + IoLib + +[Guids] + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiCpuArchProtocolGuid + gEfiDevicePathProtocolGuid + gEmbeddedExternalDeviceProtocolGuid + +[Pcd] + gBeagleBoardTokenSpaceGuid.PcdBeagleMMCHS1Base + +[depex] + gEmbeddedExternalDeviceProtocolGuid diff --git a/BeagleBoardPkg/PciEmulation/PciEmulation.c b/BeagleBoardPkg/PciEmulation/PciEmulation.c new file mode 100644 index 0000000000..dee0541971 --- /dev/null +++ b/BeagleBoardPkg/PciEmulation/PciEmulation.c @@ -0,0 +1,584 @@ +/** @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 "PciEmulation.h" +#include <Omap3530/Omap3530.h> + +EFI_CPU_ARCH_PROTOCOL *gCpu; +EMBEDDED_EXTERNAL_DEVICE *gTPS65950; + +#define HOST_CONTROLLER_OPERATION_REG_SIZE 0x44 + +typedef struct { + ACPI_HID_DEVICE_PATH AcpiDevicePath; + PCI_DEVICE_PATH PciDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} EFI_PCI_IO_DEVICE_PATH; + +typedef struct { + UINT32 Signature; + EFI_PCI_IO_DEVICE_PATH DevicePath; + EFI_PCI_IO_PROTOCOL PciIoProtocol; + PCI_TYPE00 *ConfigSpace; + PCI_ROOT_BRIDGE RootBridge; + UINTN Segment; +} EFI_PCI_IO_PRIVATE_DATA; + +#define EFI_PCI_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'o') +#define EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(a) CR(a, EFI_PCI_IO_PRIVATE_DATA, PciIoProtocol, EFI_PCI_IO_PRIVATE_DATA_SIGNATURE) + +EFI_PCI_IO_DEVICE_PATH PciIoDevicePathTemplate = +{ + { + { ACPI_DEVICE_PATH, ACPI_DP, sizeof (ACPI_HID_DEVICE_PATH), 0}, + EISA_PNP_ID(0x0A03), // HID + 0 // UID + }, + { + { HARDWARE_DEVICE_PATH, HW_PCI_DP, sizeof (PCI_DEVICE_PATH), 0}, + 0, + 0 + }, + { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} +}; + +STATIC +VOID +ConfigureUSBHost ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 Data = 0; + + // Take USB host out of force-standby mode + MmioWrite32(UHH_SYSCONFIG, UHH_SYSCONFIG_MIDLEMODE_NO_STANDBY + | UHH_SYSCONFIG_CLOCKACTIVITY_ON + | UHH_SYSCONFIG_SIDLEMODE_NO_STANDBY + | UHH_SYSCONFIG_ENAWAKEUP_ENABLE + | UHH_SYSCONFIG_AUTOIDLE_ALWAYS_RUN); + MmioWrite32(UHH_HOSTCONFIG, UHH_HOSTCONFIG_P3_CONNECT_STATUS_DISCONNECT + | UHH_HOSTCONFIG_P2_CONNECT_STATUS_DISCONNECT + | UHH_HOSTCONFIG_P1_CONNECT_STATUS_DISCONNECT + | UHH_HOSTCONFIG_ENA_INCR_ALIGN_DISABLE + | UHH_HOSTCONFIG_ENA_INCR16_ENABLE + | UHH_HOSTCONFIG_ENA_INCR8_ENABLE + | UHH_HOSTCONFIG_ENA_INCR4_ENABLE + | UHH_HOSTCONFIG_AUTOPPD_ON_OVERCUR_EN_ON + | UHH_HOSTCONFIG_P1_ULPI_BYPASS_ULPI_MODE); + + // USB reset (GPIO 147 - Port 5 pin 19) output high + MmioAnd32(GPIO5_BASE + GPIO_OE, ~BIT19); + MmioWrite32(GPIO5_BASE + GPIO_SETDATAOUT, BIT19); + + // Get the Power IC protocol. + Status = gBS->LocateProtocol(&gEmbeddedExternalDeviceProtocolGuid, NULL, (VOID **)&gTPS65950); + ASSERT_EFI_ERROR(Status); + + //Enable power to the USB host. + Status = gTPS65950->Read(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data); + ASSERT_EFI_ERROR(Status); + + //LEDAON & LEDAPWM control the power to the USB host so enable those bits. + Data |= (LEDAON | LEDAPWM); + + Status = gTPS65950->Write(gTPS65950, EXTERNAL_DEVICE_REGISTER(I2C_ADDR_GRP_ID3, LEDEN), 1, &Data); + ASSERT_EFI_ERROR(Status); +} + +EFI_STATUS +PciIoPollMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoPollIo ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoMemRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemRead (&Private->RootBridge.Io, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Private->ConfigSpace->Device.Bar[BarIndex] + Offset, + Count, + Buffer + ); +} + +EFI_STATUS +PciIoMemWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemWrite (&Private->RootBridge.Io, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Private->ConfigSpace->Device.Bar[BarIndex] + Offset, + Count, + Buffer + ); +} + +EFI_STATUS +PciIoIoRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoIoWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoPciRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH)Width, + Count, + TRUE, + (PTR)(UINTN)Buffer, + TRUE, + (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset) + ); +} + +EFI_STATUS +PciIoPciWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + return PciRootBridgeIoMemRW ((EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Count, + TRUE, + (PTR)(UINTN)(((UINT8 *)Private->ConfigSpace) + Offset), + TRUE, + (PTR)(UINTN)Buffer + ); +} + +EFI_STATUS +PciIoCopyMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoMap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + MAP_INFO_INSTANCE *Map; + EFI_STATUS Status; + + if ( HostAddress == NULL || NumberOfBytes == NULL || + DeviceAddress == NULL || Mapping == NULL ) { + + return EFI_INVALID_PARAMETER; + } + + + if (Operation >= EfiPciOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + *DeviceAddress = ConvertToPhysicalAddress (HostAddress); + + // Data cache flush (HostAddress, NumberOfBytes); + + // Remember range so we can flush on the other side + Status = gBS->AllocatePool (EfiBootServicesData, sizeof (PCI_DMA_MAP), (VOID **) &Map); + if (EFI_ERROR(Status)) { + return EFI_OUT_OF_RESOURCES; + } + + *Mapping = Map; + + Map->HostAddress = (UINTN)HostAddress; + Map->DeviceAddress = *DeviceAddress; + Map->NumberOfBytes = *NumberOfBytes; + Map->Operation = Operation; + + // EfiCpuFlushTypeWriteBack, EfiCpuFlushTypeInvalidate + gCpu->FlushDataCache (gCpu, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, *NumberOfBytes, EfiCpuFlushTypeWriteBackInvalidate); + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ) +{ + PCI_DMA_MAP *Map; + + if (Mapping == NULL) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + Map = (PCI_DMA_MAP *)Mapping; + if (Map->Operation == EfiPciOperationBusMasterWrite) { + // + // Make sure we read buffer from uncached memory and not the cache + // + gCpu->FlushDataCache (gCpu, Map->HostAddress, Map->NumberOfBytes, EfiCpuFlushTypeInvalidate); + } else if (Map->Operation == EfiPciOperationBusMasterCommonBuffer) { + // + // CPU was using uncached address, so anything in the cached range is bogus + // + gCpu->FlushDataCache (gCpu, Map->DeviceAddress, Map->NumberOfBytes, EfiCpuFlushTypeInvalidate); + } + + FreePool (Map); + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoAllocateBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + if (Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) { + return EFI_UNSUPPORTED; + } + + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData + // + // We used uncached memory to keep coherency + // + if (MemoryType == EfiBootServicesData) { + *HostAddress = UncachedAllocatePages (Pages); + } else if (MemoryType != EfiRuntimeServicesData) { + *HostAddress = UncachedAllocateRuntimePages (Pages); + } else { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + if (HostAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + UncachedFreePages (HostAddress, Pages); + return EFI_SUCCESS; +} + + +EFI_STATUS +PciIoFlush ( + IN EFI_PCI_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoGetLocation ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *SegmentNumber, + OUT UINTN *BusNumber, + OUT UINTN *DeviceNumber, + OUT UINTN *FunctionNumber + ) +{ + EFI_PCI_IO_PRIVATE_DATA *Private = EFI_PCI_IO_PRIVATE_DATA_FROM_THIS(This); + + if (SegmentNumber != NULL) { + *SegmentNumber = Private->Segment; + } + + if (BusNumber != NULL) { + *BusNumber = 0xff; + } + + if (DeviceNumber != NULL) { + *DeviceNumber = 0; + } + + if (FunctionNumber != NULL) { + *FunctionNumber = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ) +{ + switch (Operation) { + case EfiPciIoAttributeOperationGet: + case EfiPciIoAttributeOperationSupported: + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + // We are not a real PCI device so just say things we kind of do + *Result = EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_DEVICE_ENABLE; + break; + + case EfiPciIoAttributeOperationSet: + case EfiPciIoAttributeOperationEnable: + case EfiPciIoAttributeOperationDisable: + // Since we are not a real PCI device no enable/set or disable operations exist. + return EFI_SUCCESS; + break; + + default: + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + }; + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoGetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +PciIoSetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} + +EFI_PCI_IO_PROTOCOL PciIoTemplate = +{ + PciIoPollMem, + PciIoPollIo, + PciIoMemRead, + PciIoMemWrite, + PciIoIoRead, + PciIoIoWrite, + PciIoPciRead, + PciIoPciWrite, + PciIoCopyMem, + PciIoMap, + PciIoUnmap, + PciIoAllocateBuffer, + PciIoFreeBuffer, + PciIoFlush, + PciIoGetLocation, + PciIoAttributes, + PciIoGetBarAttributes, + PciIoSetBarAttributes, + 0, + 0 +}; + +EFI_STATUS +EFIAPI +PciEmulationEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_PCI_IO_PRIVATE_DATA *Private; + UINT8 CapabilityLength; + UINT8 PhysicalPorts; + UINTN Count; + + // Get the Cpu protocol for later use + Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&gCpu); + ASSERT_EFI_ERROR(Status); + + //Configure USB host for OMAP3530. + ConfigureUSBHost(); + + // Create a private structure + Private = AllocatePool(sizeof(EFI_PCI_IO_PRIVATE_DATA)); + if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; + return Status; + } + + Private->Signature = EFI_PCI_IO_PRIVATE_DATA_SIGNATURE; // Fill in signature + Private->RootBridge.Signature = PCI_ROOT_BRIDGE_SIGNATURE; // Fake Root Bridge structure needs a signature too + Private->RootBridge.MemoryStart = USB_EHCI_HCCAPBASE; // Get the USB capability register base + Private->Segment = 0; // Default to segment zero + + // Find out the capability register length and number of physical ports. + CapabilityLength = MmioRead8(Private->RootBridge.MemoryStart); + PhysicalPorts = (MmioRead32(Private->RootBridge.MemoryStart + 0x4)) & 0x0000000F; + + // Calculate the total size of the USB registers. + Private->RootBridge.MemorySize = CapabilityLength + (HOST_CONTROLLER_OPERATION_REG_SIZE + ((4 * PhysicalPorts) - 1)); + + // Enable Port Power bit in Port status and control registers in EHCI register space. + // Port Power Control (PPC) bit in the HCSPARAMS register is already set which indicates + // host controller implementation includes port power control. + for (Count = 0; Count < PhysicalPorts; Count++) { + MmioOr32((Private->RootBridge.MemoryStart + CapabilityLength + HOST_CONTROLLER_OPERATION_REG_SIZE + 4*Count), 0x00001000); + } + + // Create fake PCI config space. + Private->ConfigSpace = AllocateZeroPool(sizeof(PCI_TYPE00)); + if (Private->ConfigSpace == NULL) { + Status = EFI_OUT_OF_RESOURCES; + FreePool(Private); + return Status; + } + + // Configure PCI config space + Private->ConfigSpace->Hdr.VendorId = 0x3530; + Private->ConfigSpace->Hdr.DeviceId = 0x3530; + Private->ConfigSpace->Hdr.ClassCode[0] = 0x20; + Private->ConfigSpace->Hdr.ClassCode[1] = 0x03; + Private->ConfigSpace->Hdr.ClassCode[2] = 0x0C; + Private->ConfigSpace->Device.Bar[0] = Private->RootBridge.MemoryStart; + + Handle = NULL; + + // Unique device path. + CopyMem(&Private->DevicePath, &PciIoDevicePathTemplate, sizeof(PciIoDevicePathTemplate)); + Private->DevicePath.AcpiDevicePath.UID = 0; + + // Copy protocol structure + CopyMem(&Private->PciIoProtocol, &PciIoTemplate, sizeof(PciIoTemplate)); + + Status = gBS->InstallMultipleProtocolInterfaces(&Handle, + &gEfiPciIoProtocolGuid, &Private->PciIoProtocol, + &gEfiDevicePathProtocolGuid, &Private->DevicePath, + NULL); + if (EFI_ERROR(Status)) { + DEBUG((EFI_D_ERROR, "PciEmulationEntryPoint InstallMultipleProtocolInterfaces() failed.\n")); + } + + return Status; +} + diff --git a/BeagleBoardPkg/PciEmulation/PciEmulation.h b/BeagleBoardPkg/PciEmulation/PciEmulation.h new file mode 100644 index 0000000000..c19cd8c551 --- /dev/null +++ b/BeagleBoardPkg/PciEmulation/PciEmulation.h @@ -0,0 +1,305 @@ +/** @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 _PCI_ROOT_BRIDGE_H_
+#define _PCI_ROOT_BRIDGE_H_
+
+#include <PiDxe.h>
+
+#include <TPS65950.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UncachedMemoryAllocationLib.h>
+
+#include <Protocol/EmbeddedExternalDevice.h>
+#include <Protocol/Cpu.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+
+#include <IndustryStandard/Pci22.h>
+#include <IndustryStandard/Acpi.h>
+
+extern EFI_CPU_ARCH_PROTOCOL *gCpu;
+
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL
+
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+
+#define ACPI_CONFIG_IO 0
+#define ACPI_CONFIG_MMIO 1
+#define ACPI_CONFIG_BUS 2
+
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Desc[3];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesc;
+} ACPI_CONFIG_INFO;
+
+
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32 ('P', 'c', 'i', 'F')
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
+
+ UINT8 StartBus;
+ UINT8 EndBus;
+ UINT16 Type;
+ UINT32 MemoryStart;
+ UINT32 MemorySize;
+ UINTN IoOffset;
+ UINT32 IoStart;
+ UINT32 IoSize;
+ UINT64 PciAttributes;
+
+ ACPI_CONFIG_INFO *Config;
+
+} PCI_ROOT_BRIDGE;
+
+
+#define INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) CR (a, PCI_ROOT_BRIDGE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+
+typedef union {
+ UINT8 volatile *buf;
+ UINT8 volatile *ui8;
+ UINT16 volatile *ui16;
+ UINT32 volatile *ui32;
+ UINT64 volatile *ui64;
+ UINTN volatile ui;
+} PTR;
+
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ UINTN NumberOfBytes;
+ EFI_PCI_IO_PROTOCOL_OPERATION Operation;
+
+} MAP_INFO_INSTANCE;
+
+
+typedef struct {
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ UINTN NumberOfBytes;
+ EFI_PCI_IO_PROTOCOL_OPERATION Operation;
+} PCI_DMA_MAP;
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+//
+// Private Function Prototypes
+//
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ );
+
+BOOLEAN
+PciIoMemAddressValid (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Address
+ );
+
+EFI_STATUS
+EmulatePciIoForEhci (
+ INTN MvPciIfMaxIf
+ );
+
+#endif
+
diff --git a/BeagleBoardPkg/PciEmulation/PciEmulation.inf b/BeagleBoardPkg/PciEmulation/PciEmulation.inf new file mode 100644 index 0000000000..a6958b197b --- /dev/null +++ b/BeagleBoardPkg/PciEmulation/PciEmulation.inf @@ -0,0 +1,58 @@ +#%HEADER%
+/** @file
+
+ Copyright (c) 2009 Apple, Inc. All rights reserved.
+
+ This document is the property of Apple, Inc.
+ It is considered confidential and proprietary.
+
+ This document may not be reproduced or transmitted in any form,
+ in whole or in part, without the express written permission of
+ Apple, Inc.
+
+**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BeagleBoardPciEmulation
+ FILE_GUID = feaa2e2b-53ac-4d5e-ae10-1efd5da4a2ba
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = PciEmulationEntryPoint
+
+[Sources.common]
+ PciRootBridgeIo.c
+ PciEmulation.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ BeagleBoardPkg/BeagleBoardPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DxeServicesTableLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ UncachedMemoryAllocationLib
+ IoLib
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiPciHostBridgeResourceAllocationProtocolGuid
+ gEfiCpuArchProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEmbeddedExternalDeviceProtocolGuid
+
+[Depex]
+ gEfiMetronomeArchProtocolGuid AND
+ gEfiCpuArchProtocolGuid AND
+ gEmbeddedExternalDeviceProtocolGuid
+
\ No newline at end of file diff --git a/BeagleBoardPkg/PciEmulation/PciRootBridgeIo.c b/BeagleBoardPkg/PciEmulation/PciRootBridgeIo.c new file mode 100644 index 0000000000..d06a56ce57 --- /dev/null +++ b/BeagleBoardPkg/PciEmulation/PciRootBridgeIo.c @@ -0,0 +1,306 @@ +/** @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 "PciEmulation.h"
+
+BOOLEAN
+PciRootBridgeMemAddressValid (
+ IN PCI_ROOT_BRIDGE *Private,
+ IN UINT64 Address
+ )
+{
+ if ((Address >= Private->MemoryStart) && (Address < (Private->MemoryStart + Private->MemorySize))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+EFI_STATUS
+PciRootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN BOOLEAN InStrideFlag,
+ IN PTR In,
+ IN BOOLEAN OutStrideFlag,
+ OUT PTR Out
+ )
+{
+ UINTN Stride;
+ UINTN InStride;
+ UINTN OutStride;
+
+
+ Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
+ Stride = (UINTN)1 << Width;
+ InStride = InStrideFlag ? Stride : 0;
+ OutStride = OutStrideFlag ? Stride : 0;
+
+ //
+ // Loop for each iteration and move the data
+ //
+ switch (Width) {
+ case EfiPciWidthUint8:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ *In.ui8 = *Out.ui8;
+ }
+ break;
+ case EfiPciWidthUint16:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ *In.ui16 = *Out.ui16;
+ }
+ break;
+ case EfiPciWidthUint32:
+ for (;Count > 0; Count--, In.buf += InStride, Out.buf += OutStride) {
+ *In.ui32 = *Out.ui32;
+ }
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN OUT VOID *UserBuffer
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE *Private;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (!PciRootBridgeMemAddressValid (Private, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ In.buf = Buffer;
+ Out.buf = (VOID *)(UINTN) Address;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+
+ default:
+ break;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ PCI_ROOT_BRIDGE *Private;
+ UINTN AlignMask;
+ PTR In;
+ PTR Out;
+
+ if ( Buffer == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (!PciRootBridgeMemAddressValid (Private, Address)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AlignMask = (1 << (Width & 0x03)) - 1;
+ if (Address & AlignMask) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ In.buf = (VOID *)(UINTN) Address;
+ Out.buf = Buffer;
+
+ switch (Width) {
+ case EfiPciWidthUint8:
+ case EfiPciWidthUint16:
+ case EfiPciWidthUint32:
+ case EfiPciWidthUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, TRUE, Out);
+
+ case EfiPciWidthFifoUint8:
+ case EfiPciWidthFifoUint16:
+ case EfiPciWidthFifoUint32:
+ case EfiPciWidthFifoUint64:
+ return PciRootBridgeIoMemRW (Width, Count, FALSE, In, TRUE, Out);
+
+ case EfiPciWidthFillUint8:
+ case EfiPciWidthFillUint16:
+ case EfiPciWidthFillUint32:
+ case EfiPciWidthFillUint64:
+ return PciRootBridgeIoMemRW (Width, Count, TRUE, In, FALSE, Out);
+
+ default:
+ break;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciRootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Width Signifies the width of the memory operations.
+ @param Address The base address of the memory operations.
+ @param Count The number of memory operations to perform.
+ @param Buffer For read operations, the destination buffer to store the results. For write
+ operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PciRootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciRootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+
diff --git a/BeagleBoardPkg/Sec/Arm/Macro.inc b/BeagleBoardPkg/Sec/Arm/Macro.inc new file mode 100755 index 0000000000..cacfef976a --- /dev/null +++ b/BeagleBoardPkg/Sec/Arm/Macro.inc @@ -0,0 +1,67 @@ +//%HEADER%
+ MACRO
+ MmioWrite32Macro $Address, $Data
+ ldr r1, = ($Address)
+ ldr r0, = ($Data)
+ str r0, [r1]
+ MEND + + MACRO
+ MmioOr32Macro $Address, $OrData
+ ldr r1, =($Address)
+ ldr r2, =($OrData)
+ ldr r0, [r1]
+ orr r0, r0, r2
+ str r0, [r1]
+ MEND + + MACRO
+ MmioAnd32Macro $Address, $AndData
+ ldr r1, =($Address)
+ ldr r2, =($AndData)
+ ldr r0, [r1]
+ and r0, r0, r2
+ str r0, [r1]
+ MEND + + MACRO
+ MmioAndThenOr32Macro $Address, $AndData, $OrData
+ ldr r1, =($Address)
+ ldr r0, [r1]
+ ldr r2, =($AndData)
+ and r0, r0, r2
+ ldr r2, =($OrData)
+ orr r0, r0, r2
+ str r0, [r1]
+ MEND + + MACRO
+ MmioWriteFromReg32Macro $Address, $Reg
+ ldr r1, =($Address)
+ str $Reg, [r1]
+ MEND + + MACRO
+ MmioRead32Macro $Address
+ ldr r1, =($Address)
+ ldr r0, [r1]
+ MEND + + MACRO
+ MmioReadToReg32Macro $Address, $Reg
+ ldr r1, =($Address)
+ ldr $Reg, [r1]
+ MEND + + MACRO
+ LoadConstantMacro $Data
+ ldr r0, =($Data)
+ MEND + + MACRO
+ LoadConstantToRegMacro $Data, $Reg
+ ldr $Reg, =($Data)
+ MEND
+
+ END
+
\ No newline at end of file diff --git a/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.S b/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.S new file mode 100755 index 0000000000..0ae8da6a24 --- /dev/null +++ b/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.S @@ -0,0 +1,93 @@ +#------------------------------------------------------------------------------
+#
+# 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 <AsmMacroIoLib.h>
+#include <Library/PcdLib.h>
+
+.text
+.align 3
+
+.globl ASM_PFX(CEntryPoint)
+.globl ASM_PFX(_ModuleEntryPoint)
+
+ASM_PFX(_ModuleEntryPoint):
+
+ //Disable L2 cache
+ mrc p15, 0, r0, c1, c0, 1 // read Auxiliary Control Register
+ bic r0, r0, #0x00000002 // disable L2 cache
+ mcr p15, 0, r0, c1, c0, 1 // store Auxiliary Control Register
+
+ //Enable Strict alignment checking & Instruction cache
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
+ bic r0, r0, #0x00000005 /* clear bits 0, 2 (---- -C-M) */
+ orr r0, r0, #0x00000002 /* set bit 1 (A) Align */
+ orr r0, r0, #0x00001000 /* set bit 12 (I) enable I-Cache */
+ mcr p15, 0, r0, c1, c0, 0
+
+ // Set CPU vectors to start of DRAM
+ mov r0, #0x80000000
+ mcr p15, 0, r0, c12, c0, 0
+
+ /* before we call C code, lets setup the stack pointer */
+stack_pointer_setup:
+
+ //
+ // Set stack based on PCD values. Need to do it this way to make C code work
+ // when it runs from FLASH.
+ //
+ LoadConstantToReg (FixedPcdGet32(PcdPrePiStackBase) ,r2) /* stack base arg2 */
+ LoadConstantToReg (FixedPcdGet32(PcdPrePiStackSize) ,r3) /* stack size arg3 */
+ add r4, r2, r3
+
+ //Enter IRQ mode and set up IRQ stack pointer
+ mov r0,#0x12|0x80|0x40
+ msr CPSR_c,r0
+ mov r13,r4
+
+ //Enter Abort mode and set up Abort stack pointer
+ mov r0,#0x17|0x80|0x40
+ msr CPSR_c,r0
+ sub r4, r4, #0x400
+ mov r13,r4
+
+ //Enter Undefined mode and set up Undefined stack pointer
+ mov r0,#0x1b|0x80|0x40
+ msr CPSR_c,r0
+ sub r4, r4, #0x400
+ mov r13,r4
+
+ //Enter SVC mode and set up SVC stack pointer
+ mov r0,#0x13|0x80|0x40
+ msr CPSR_c,r0
+ sub r4, r4, #0x400
+ mov r13,r4
+
+ //Enter System mode and set up System stack pointer
+ mov r0,#0x1f|0x80|0x40
+ msr CPSR_c,r0
+ sub r4, r4, #0x400
+ mov r13,r4
+
+ // Call C entry point
+ mov r0, #0x80000000 /* memory base arg0 */
+ mov r1, #0x10000000 /* memory size arg1 */
+
+ bl ASM_PFX(CEntryPoint) /* Assume C code is ARM */
+
+ShouldNeverGetHere:
+ /* _CEntryPoint should never return */
+ b ShouldNeverGetHere
+
+
diff --git a/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.asm b/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.asm new file mode 100755 index 0000000000..fb30e4dd59 --- /dev/null +++ b/BeagleBoardPkg/Sec/Arm/ModuleEntryPoint.asm @@ -0,0 +1,95 @@ +//------------------------------------------------------------------------------
+//
+// 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 <AsmMacroIoLib.h>
+#include <Library/PcdLib.h>
+#include <AutoGen.h>
+ INCLUDE AsmMacroIoLib.inc
+
+ IMPORT CEntryPoint
+ EXPORT _ModuleEntryPoint
+
+ PRESERVE8
+ AREA ModuleEntryPoint, CODE, READONLY
+
+
+_ModuleEntryPoint
+
+ //Disable L2 cache
+ mrc p15, 0, r0, c1, c0, 1 // read Auxiliary Control Register
+ bic r0, r0, #0x00000002 // disable L2 cache
+ mcr p15, 0, r0, c1, c0, 1 // store Auxiliary Control Register
+
+ //Enable Strict alignment checking & Instruction cache
+ mrc p15, 0, r0, c1, c0, 0
+ bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
+ bic r0, r0, #0x00000005 /* clear bits 0, 2 (---- -C-M) */
+ orr r0, r0, #0x00000002 /* set bit 1 (A) Align */
+ orr r0, r0, #0x00001000 /* set bit 12 (I) enable I-Cache */
+ mcr p15, 0, r0, c1, c0, 0
+
+ // Set CPU vectors to start of DRAM
+ mov r0, #0x80000000
+ mcr p15, 0, r0, c12, c0, 0
+ /* before we call C code, lets setup the stack pointer in internal RAM*/
+stack_pointer_setup
+
+ //
+ // Set stack based on PCD values. Need to do it this way to make C code work
+ // when it runs from FLASH.
+ //
+ LoadConstantToReg (FixedPcdGet32(PcdPrePiStackBase) ,r2) /* stack base arg2 */
+ LoadConstantToReg (FixedPcdGet32(PcdPrePiStackSize) ,r3) /* stack size arg3 */
+ add r4, r2, r3
+
+ //Enter IRQ mode and set up IRQ stack pointer
+ mov r0,#0x12|0x80|0x40
+ msr CPSR_c,r0
+ mov r13,r4
+
+ //Enter Abort mode and set up Abort stack pointer
+ mov r0,#0x17|0x80|0x40
+ msr CPSR_c,r0
+ sub r4, r4, #0x400
+ mov r13,r4
+
+ //Enter Undefined mode and set up Undefined stack pointer
+ mov r0,#0x1b|0x80|0x40
+ msr CPSR_c,r0
+ sub r4, r4, #0x400
+ mov r13,r4
+
+ //Enter SVC mode and set up SVC stack pointer
+ mov r0,#0x13|0x80|0x40
+ msr CPSR_c,r0
+ sub r4, r4, #0x400
+ mov r13,r4
+
+ //Enter System mode and set up System stack pointer
+ mov r0,#0x1f|0x80|0x40
+ msr CPSR_c,r0
+ sub r4, r4, #0x400
+ mov r13,r4
+
+ // Call C entry point
+ mov r0, #0x80000000 /* memory base arg0 */
+ mov r1, #0x08000000 /* memory size arg1 */
+ blx CEntryPoint /* Assume C code is thumb */
+
+ShouldNeverGetHere
+ /* _CEntryPoint should never return */
+ b ShouldNeverGetHere
+
+ END
+
diff --git a/BeagleBoardPkg/Sec/Cache.c b/BeagleBoardPkg/Sec/Cache.c new file mode 100755 index 0000000000..12bf990812 --- /dev/null +++ b/BeagleBoardPkg/Sec/Cache.c @@ -0,0 +1,88 @@ +/** @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/ArmLib.h>
+#include <Library/PrePiLib.h>
+#include <Library/PcdLib.h>
+
+// DDR attributes
+#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
+#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
+
+// SoC registers. L3 interconnects
+#define SOC_REGISTERS_L3_PHYSICAL_BASE 0x68000000
+#define SOC_REGISTERS_L3_PHYSICAL_LENGTH 0x08000000
+#define SOC_REGISTERS_L3_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_DEVICE
+
+// SoC registers. L4 interconnects
+#define SOC_REGISTERS_L4_PHYSICAL_BASE 0x48000000
+#define SOC_REGISTERS_L4_PHYSICAL_LENGTH 0x08000000
+#define SOC_REGISTERS_L4_ATTRIBUTES ARM_MEMORY_REGION_ATTRIBUTE_DEVICE
+
+VOID
+InitCache (
+ IN UINT32 MemoryBase,
+ IN UINT32 MemoryLength
+ )
+{
+ UINTN UncachedMemoryMask;
+ UINT32 CacheAttributes;
+ ARM_MEMORY_REGION_DESCRIPTOR MemoryTable[5];
+ VOID *TranslationTableBase;
+ UINTN TranslationTableSize;
+
+ UncachedMemoryMask = PcdGet64(PcdArmUncachedMemoryMask);
+
+ if (FeaturePcdGet(PcdCacheEnable) == TRUE) {
+ CacheAttributes = DDR_ATTRIBUTES_CACHED;
+ } else {
+ CacheAttributes = DDR_ATTRIBUTES_UNCACHED;
+ }
+
+ // DDR
+ MemoryTable[0].PhysicalBase = MemoryBase;
+ MemoryTable[0].VirtualBase = MemoryBase;
+ MemoryTable[0].Length = MemoryLength;
+ MemoryTable[0].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)CacheAttributes;
+
+ // Uncached DDR Mirror
+ MemoryTable[1].PhysicalBase = MemoryBase;
+ MemoryTable[1].VirtualBase = MemoryBase | UncachedMemoryMask;
+ MemoryTable[1].Length = MemoryLength;
+ MemoryTable[1].Attributes = DDR_ATTRIBUTES_UNCACHED;
+
+ // SOC Registers. L3 interconnects
+ MemoryTable[2].PhysicalBase = SOC_REGISTERS_L3_PHYSICAL_BASE;
+ MemoryTable[2].VirtualBase = SOC_REGISTERS_L3_PHYSICAL_BASE;
+ MemoryTable[2].Length = SOC_REGISTERS_L3_PHYSICAL_LENGTH;
+ MemoryTable[2].Attributes = SOC_REGISTERS_L3_ATTRIBUTES;
+
+ // SOC Registers. L4 interconnects
+ MemoryTable[3].PhysicalBase = SOC_REGISTERS_L4_PHYSICAL_BASE;
+ MemoryTable[3].VirtualBase = SOC_REGISTERS_L4_PHYSICAL_BASE;
+ MemoryTable[3].Length = SOC_REGISTERS_L4_PHYSICAL_LENGTH;
+ MemoryTable[3].Attributes = SOC_REGISTERS_L4_ATTRIBUTES;
+
+ // End of Table
+ MemoryTable[4].PhysicalBase = 0;
+ MemoryTable[4].VirtualBase = 0;
+ MemoryTable[4].Length = 0;
+ MemoryTable[4].Attributes = (ARM_MEMORY_REGION_ATTRIBUTES)0;
+
+ ArmConfigureMmu(MemoryTable, &TranslationTableBase, &TranslationTableSize);
+
+ BuildMemoryAllocationHob((EFI_PHYSICAL_ADDRESS)(UINTN)TranslationTableBase, TranslationTableSize, EfiBootServicesData);
+}
diff --git a/BeagleBoardPkg/Sec/Clock.c b/BeagleBoardPkg/Sec/Clock.c new file mode 100644 index 0000000000..2d814e49e9 --- /dev/null +++ b/BeagleBoardPkg/Sec/Clock.c @@ -0,0 +1,70 @@ +/** @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 <Library/IoLib.h>
+#include <Library/DebugLib.h>
+
+#include <Omap3530/Omap3530.h>
+
+VOID
+ClockInit (
+ VOID
+ )
+{
+ //DPLL1 - DPLL4 are configured part of Configuration header which OMAP3 ROM parses.
+
+ // Enable PLL5 and set to 120 MHz as a reference clock.
+ MmioWrite32(CM_CLKSEL4_PLL, CM_CLKSEL_PLL_MULT(120) | CM_CLKSEL_PLL_DIV(13));
+ MmioWrite32(CM_CLKSEL5_PLL, CM_CLKSEL_DIV_120M(1));
+ MmioWrite32(CM_CLKEN2_PLL, CM_CLKEN_FREQSEL_075_100 | CM_CLKEN_ENABLE);
+
+ // Turn on functional & interface clocks to the USBHOST power domain
+ MmioOr32(CM_FCLKEN_USBHOST, CM_FCLKEN_USBHOST_EN_USBHOST2_ENABLE
+ | CM_FCLKEN_USBHOST_EN_USBHOST1_ENABLE);
+ MmioOr32(CM_ICLKEN_USBHOST, CM_ICLKEN_USBHOST_EN_USBHOST_ENABLE);
+
+ // Turn on functional & interface clocks to the USBTLL block.
+ MmioOr32(CM_FCLKEN3_CORE, CM_FCLKEN3_CORE_EN_USBTLL_ENABLE);
+ MmioOr32(CM_ICLKEN3_CORE, CM_ICLKEN3_CORE_EN_USBTLL_ENABLE);
+
+ // Turn on functional & interface clocks to MMC1 and I2C1 modules.
+ MmioOr32(CM_FCLKEN1_CORE, CM_FCLKEN1_CORE_EN_MMC1_ENABLE
+ | CM_FCLKEN1_CORE_EN_I2C1_ENABLE);
+ MmioOr32(CM_ICLKEN1_CORE, CM_ICLKEN1_CORE_EN_MMC1_ENABLE
+ | CM_ICLKEN1_CORE_EN_I2C1_ENABLE);
+
+ // Turn on functional & interface clocks to various Peripherals.
+ MmioOr32(CM_FCLKEN_PER, CM_FCLKEN_PER_EN_UART3_ENABLE
+ | CM_FCLKEN_PER_EN_GPT3_ENABLE
+ | CM_FCLKEN_PER_EN_GPT4_ENABLE
+ | CM_FCLKEN_PER_EN_GPIO2_ENABLE
+ | CM_FCLKEN_PER_EN_GPIO3_ENABLE
+ | CM_FCLKEN_PER_EN_GPIO4_ENABLE
+ | CM_FCLKEN_PER_EN_GPIO5_ENABLE
+ | CM_FCLKEN_PER_EN_GPIO6_ENABLE);
+ MmioOr32(CM_ICLKEN_PER, CM_ICLKEN_PER_EN_UART3_ENABLE
+ | CM_ICLKEN_PER_EN_GPT3_ENABLE
+ | CM_ICLKEN_PER_EN_GPT4_ENABLE
+ | CM_ICLKEN_PER_EN_GPIO2_ENABLE
+ | CM_ICLKEN_PER_EN_GPIO3_ENABLE
+ | CM_ICLKEN_PER_EN_GPIO4_ENABLE
+ | CM_ICLKEN_PER_EN_GPIO5_ENABLE
+ | CM_ICLKEN_PER_EN_GPIO6_ENABLE);
+
+ // Turn on functional & inteface clocks to various wakeup modules.
+ MmioOr32(CM_FCLKEN_WKUP, CM_FCLKEN_WKUP_EN_GPIO1_ENABLE
+ | CM_FCLKEN_WKUP_EN_WDT2_ENABLE);
+ MmioOr32(CM_ICLKEN_WKUP, CM_ICLKEN_WKUP_EN_GPIO1_ENABLE
+ | CM_ICLKEN_WKUP_EN_WDT2_ENABLE);
+}
diff --git a/BeagleBoardPkg/Sec/PadConfiguration.c b/BeagleBoardPkg/Sec/PadConfiguration.c new file mode 100644 index 0000000000..b478cdfd92 --- /dev/null +++ b/BeagleBoardPkg/Sec/PadConfiguration.c @@ -0,0 +1,282 @@ +/** @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/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Omap3530/Omap3530.h>
+
+#define NUM_PINS 238
+
+PAD_CONFIGURATION PadConfigurationTable[NUM_PINS] = {
+ //Pin, MuxMode, PullConfig, InputEnable
+ { SDRC_D0, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D1, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D2, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D3, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D4, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D5, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D6, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D7, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D8, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D9, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D10, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D11, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D12, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D13, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D14, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D15, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D16, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D17, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D18, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D19, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D20, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D21, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D22, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D23, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D24, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D25, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D26, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D27, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D28, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D29, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D30, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_D31, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_CLK, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_DQS0, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_CKE0, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { SDRC_CKE1, MUXMODE7, PULLTYPENOSELECT, INPUT },
+ { SDRC_DQS1, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_DQS2, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { SDRC_DQS3, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_A1, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_A2, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_A3, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_A4, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_A5, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_A6, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_A7, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_A8, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_A9, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_A10, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_D0, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D1, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D2, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D3, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D4, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D5, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D6, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D7, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D8, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D9, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D10, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D11, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D12, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D13, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D14, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_D15, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_NCS0, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_NCS1, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT },
+ { GPMC_NCS2, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT },
+ { GPMC_NCS3, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT },
+ { GPMC_NCS4, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT },
+ { GPMC_NCS5, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_NCS6, MUXMODE1, PULLTYPENOSELECT, INPUT },
+ { GPMC_NCS7, MUXMODE1, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { GPMC_CLK, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_NADV_ALE, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_NOE, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_NWE, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_NBE0_CLE, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { GPMC_NBE1, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_NWP, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { GPMC_WAIT0, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { GPMC_WAIT1, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { GPMC_WAIT2, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { GPMC_WAIT3, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { DSS_PCLK, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_HSYNC, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_PSYNC, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_ACBIAS, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA0, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA1, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA2, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA3, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA4, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA5, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA6, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA7, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA8, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA9, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA10, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA11, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA12, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA13, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA14, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA15, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA16, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA17, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA18, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA19, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA20, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA21, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA22, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { DSS_DATA23, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { CAM_HS, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { CAM_VS, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { CAM_XCLKA, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { CAM_PCLK, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { CAM_FLD, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { CAM_D0, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D1, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D2, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D3, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D4, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D5, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D6, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D7, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D8, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D9, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D10, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_D11, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CAM_XCLKB, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { CAM_WEN, MUXMODE4, PULLTYPENOSELECT, INPUT },
+ { CAM_STROBE, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { CSI2_DX0, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CSI2_DY0, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CSI2_DX1, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { CSI2_DY1, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { MCBSP2_FSX, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { MCBSP2_CLKX, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { MCBSP2_DR, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { MCBSP2_DX, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { MMC1_CLK, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT },
+ { MMC1_CMD, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC1_DAT0, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC1_DAT1, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC1_DAT2, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC1_DAT3, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC1_DAT4, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC1_DAT5, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC1_DAT6, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC1_DAT7, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_CLK, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_CMD, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_DAT0, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_DAT1, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_DAT2, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_DAT3, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_DAT4, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_DAT5, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_DAT6, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MMC2_DAT7, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MCBSP3_DX, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { MCBSP3_DR, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { MCBSP3_CLKX, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { MCBSP3_FSX, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { UART2_CTS, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { UART2_RTS, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { UART2_TX, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { UART2_RX, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { UART1_TX, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { UART1_RTS, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { UART1_CTS, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { UART1_RX, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { MCBSP4_CLKX, MUXMODE1, PULLTYPENOSELECT, INPUT },
+ { MCBSP4_DR, MUXMODE1, PULLTYPENOSELECT, INPUT },
+ { MCBSP4_DX, MUXMODE1, PULLTYPENOSELECT, INPUT },
+ { MCBSP4_FSX, MUXMODE1, PULLTYPENOSELECT, INPUT },
+ { MCBSP1_CLKR, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { MCBSP1_FSR, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), OUTPUT },
+ { MCBSP1_DX, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { MCBSP1_DR, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { MCBSP1_CLKS, MUXMODE0, PULLTYPESELECT, INPUT },
+ { MCBSP1_FSX, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { MCBSP1_CLKX, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { UART3_CTS_RCTX,MUXMODE0, PULLUDENABLE, INPUT },
+ { UART3_RTS_SD, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { UART3_RX_IRRX, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { UART3_TX_IRTX, MUXMODE0, PULLTYPENOSELECT, OUTPUT },
+ { HSUSB0_CLK, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_STP, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), OUTPUT },
+ { HSUSB0_DIR, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_NXT, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_DATA0, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_DATA1, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_DATA2, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_DATA3, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_DATA4, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_DATA5, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_DATA6, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { HSUSB0_DATA7, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { I2C1_SCL, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { I2C1_SDA, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { I2C2_SCL, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { I2C2_SDA, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { I2C3_SCL, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { I2C3_SDA, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { HDQ_SIO, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), OUTPUT },
+ { MCSPI1_CLK, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MCSPI1_SIMO, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { MCSPI1_SOMI, MUXMODE0, PULLTYPENOSELECT, INPUT },
+ { MCSPI1_CS0, MUXMODE0, PULLUDENABLE, INPUT },
+ { MCSPI1_CS1, MUXMODE0, PULLUDENABLE, OUTPUT },
+ { MCSPI1_CS2, MUXMODE4, PULLTYPENOSELECT, OUTPUT },
+ { MCSPI1_CS3, MUXMODE3, PULLTYPESELECT, INPUT },
+ { MCSPI2_CLK, MUXMODE3, PULLTYPESELECT, INPUT },
+ { MCSPI2_SIMO, MUXMODE3, PULLTYPESELECT, INPUT },
+ { MCSPI2_SOMI, MUXMODE3, PULLTYPESELECT, INPUT },
+ { MCSPI2_CS0, MUXMODE3, PULLTYPESELECT, INPUT },
+ { MCSPI2_CS1, MUXMODE3, PULLTYPESELECT, INPUT },
+ { SYS_NIRQ, MUXMODE0, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { SYS_CLKOUT2, MUXMODE4, (PULLTYPESELECT | PULLUDENABLE), INPUT },
+ { ETK_CLK, MUXMODE3, (PULLTYPESELECT | PULLUDENABLE), OUTPUT },
+ { ETK_CTL, MUXMODE3, PULLTYPESELECT, OUTPUT },
+ { ETK_D0, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D1, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D2, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D3, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D4, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D5, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D6, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D7, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D8, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D9, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D10, MUXMODE3, PULLTYPESELECT, OUTPUT },
+ { ETK_D11, MUXMODE3, PULLTYPESELECT, OUTPUT },
+ { ETK_D12, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D13, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D14, MUXMODE3, PULLTYPESELECT, INPUT },
+ { ETK_D15, MUXMODE3, PULLTYPESELECT, INPUT }
+};
+
+VOID
+PadConfiguration (
+ VOID
+ )
+{
+ UINTN Index;
+ UINT16 PadConfiguration;
+ UINTN NumPinsToConfigure = sizeof(PadConfigurationTable)/sizeof(PAD_CONFIGURATION);
+
+ for (Index = 0; Index < NumPinsToConfigure; Index++) {
+ //Set up Pad configuration for particular pin.
+ PadConfiguration = (PadConfigurationTable[Index].MuxMode << MUXMODE_OFFSET);
+ PadConfiguration |= (PadConfigurationTable[Index].PullConfig << PULL_CONFIG_OFFSET);
+ PadConfiguration |= (PadConfigurationTable[Index].InputEnable << INPUTENABLE_OFFSET);
+
+ //Configure the pin with specific Pad configuration.
+ MmioWrite16(PadConfigurationTable[Index].Pin, PadConfiguration);
+ }
+}
diff --git a/BeagleBoardPkg/Sec/Sec.c b/BeagleBoardPkg/Sec/Sec.c new file mode 100755 index 0000000000..321b35940c --- /dev/null +++ b/BeagleBoardPkg/Sec/Sec.c @@ -0,0 +1,165 @@ +/** @file
+ C Entry point for the SEC. First C code after the reset vector.
+
+ 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/DebugLib.h>
+#include <Library/PrePiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/IoLib.h>
+#include <Library/OmapLib.h>
+#include <Library/ArmLib.h>
+
+#include <Ppi/GuidedSectionExtraction.h>
+
+#include <Omap3530/Omap3530.h>
+
+VOID
+PadConfiguration (
+ VOID
+ );
+
+VOID
+ClockInit (
+ VOID
+ );
+
+VOID
+TimerInit (
+ VOID
+ )
+{
+ UINTN Timer = FixedPcdGet32(PcdBeagleFreeTimer);
+ UINT32 TimerBaseAddress = TimerBase(Timer);
+
+ // Set source clock for GPT3 & GPT4 to SYS_CLK
+ MmioOr32(CM_CLKSEL_PER, CM_CLKSEL_PER_CLKSEL_GPT3_SYS
+ | CM_CLKSEL_PER_CLKSEL_GPT4_SYS);
+
+ // Set count & reload registers
+ MmioWrite32(TimerBaseAddress + GPTIMER_TCRR, 0x00000000);
+ MmioWrite32(TimerBaseAddress + GPTIMER_TLDR, 0x00000000);
+
+ // Disable interrupts
+ MmioWrite32(TimerBaseAddress + GPTIMER_TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_DISABLE | TIER_MAT_IT_DISABLE);
+
+ // Start Timer
+ MmioWrite32(TimerBaseAddress + GPTIMER_TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON);
+
+ //Disable OMAP Watchdog timer (WDT2)
+ MmioWrite32(WDTIMER2_BASE + WSPR, 0xAAAA);
+ DEBUG ((EFI_D_ERROR, "Magic delay to disable watchdog timers properly.\n"));
+ MmioWrite32(WDTIMER2_BASE + WSPR, 0x5555);
+}
+
+VOID
+UartInit (
+ VOID
+ )
+{
+ UINTN Uart = FixedPcdGet32(PcdBeagleConsoleUart);
+ UINT32 UartBaseAddress = UartBase(Uart);
+
+ // Set MODE_SELECT=DISABLE before trying to initialize or modify DLL, DLH registers.
+ MmioWrite32(UartBaseAddress + UART_MDR1_REG, UART_MDR1_MODE_SELECT_DISABLE);
+
+ // Put device in configuration mode.
+ MmioWrite32(UartBaseAddress + UART_LCR_REG, UART_LCR_DIV_EN_ENABLE);
+
+ // Programmable divisor N = 48Mhz/16/115200 = 26
+ MmioWrite32(UartBaseAddress + UART_DLL_REG, 26); // low divisor
+ MmioWrite32(UartBaseAddress + UART_DLH_REG, 0); // high divisor
+
+ // Enter into UART operational mode.
+ MmioWrite32(UartBaseAddress + UART_LCR_REG, UART_LCR_DIV_EN_DISABLE | UART_LCR_CHAR_LENGTH_8);
+
+ // Force DTR and RTS output to active
+ MmioWrite32(UartBaseAddress + UART_MCR_REG, UART_MCR_RTS_FORCE_ACTIVE | UART_MCR_DTR_FORCE_ACTIVE);
+
+ // Clear & enable fifos
+ MmioWrite32(UartBaseAddress + UART_FCR_REG, UART_FCR_TX_FIFO_CLEAR | UART_FCR_RX_FIFO_CLEAR | UART_FCR_FIFO_ENABLE);
+
+ // Restore MODE_SELECT
+ MmioWrite32(UartBaseAddress + UART_MDR1_REG, UART_MDR1_MODE_SELECT_UART_16X);
+}
+
+VOID
+InitCache (
+ IN UINT32 MemoryBase,
+ IN UINT32 MemoryLength
+ );
+
+EFI_STATUS
+EFIAPI
+ExtractGuidedSectionLibConstructor (
+ VOID
+ );
+
+EFI_STATUS
+EFIAPI
+LzmaDecompressLibConstructor (
+ VOID
+ );
+
+VOID
+CEntryPoint (
+ IN VOID *MemoryBase,
+ IN UINTN MemorySize,
+ IN VOID *StackBase,
+ IN UINTN StackSize
+ )
+{
+ VOID *HobBase;
+
+ //Set up Pin muxing.
+ PadConfiguration();
+
+ // Set up system clocking
+ ClockInit();
+
+ // Build a basic HOB list
+ HobBase = (VOID *)(UINTN)(FixedPcdGet32(PcdEmbeddedFdBaseAddress) + FixedPcdGet32(PcdEmbeddedFdSize));
+ CreateHobList(MemoryBase, MemorySize, HobBase, StackBase);
+
+ // Enable program flow prediction, if supported.
+ ArmEnableBranchPrediction();
+
+ // Initialize CPU cache
+ InitCache((UINT32)MemoryBase, (UINT32)MemorySize);
+
+ // Add memory allocation hob for relocated FD
+ BuildMemoryAllocationHob(FixedPcdGet32(PcdEmbeddedFdBaseAddress), FixedPcdGet32(PcdEmbeddedFdSize), EfiBootServicesData);
+
+ // Add the FVs to the hob list
+ BuildFvHob(PcdGet32(PcdFlashFvMainBase), PcdGet32(PcdFlashFvMainSize));
+
+ // Start talking
+ UartInit();
+ DEBUG((EFI_D_ERROR, "UART Test Line\n"));
+
+ // Start up a free running time so that the timer lib will work
+ TimerInit();
+
+ // SEC phase needs to run library constructors by hand.
+ ExtractGuidedSectionLibConstructor();
+ LzmaDecompressLibConstructor();
+
+ // Load the DXE Core and transfer control to it
+ LoadDxeCoreFromFv(NULL, 0);
+
+ // DXE Core should always load and never return
+ ASSERT(FALSE);
+}
+
diff --git a/BeagleBoardPkg/Sec/Sec.inf b/BeagleBoardPkg/Sec/Sec.inf new file mode 100755 index 0000000000..834519cf76 --- /dev/null +++ b/BeagleBoardPkg/Sec/Sec.inf @@ -0,0 +1,66 @@ +#%HEADER% +#/** @file +# SEC - Reset vector code that jumps to C and loads DXE core +# +# 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 = BeagleBoardSec + FILE_GUID = d959e387-7b91-452c-90e0-a1dbac90ddb8 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + + +[Sources.ARM] + Arm/ModuleEntryPoint.S | GCC + Arm/ModuleEntryPoint.asm | RVCT + +[Sources.ARM] + Sec.c + Cache.c + PadConfiguration.c + Clock.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + ArmLib + IoLib + ExtractGuidedSectionLib + LzmaDecompressLib + OmapLib + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + +[FixedPcd] + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask + + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize + gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase + gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase + + gBeagleBoardTokenSpaceGuid.PcdBeagleConsoleUart + gBeagleBoardTokenSpaceGuid.PcdBeagleFreeTimer + gBeagleBoardTokenSpaceGuid.PcdBeagleBoardIRAMFullSize + diff --git a/BeagleBoardPkg/SmbusDxe/Smbus.c b/BeagleBoardPkg/SmbusDxe/Smbus.c new file mode 100644 index 0000000000..35b17eb1fb --- /dev/null +++ b/BeagleBoardPkg/SmbusDxe/Smbus.c @@ -0,0 +1,325 @@ +/** @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 <Omap3530/Omap3530.h> + +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/SmbusHc.h> + +#define MAX_RETRY 1000 + +// +// Internal Functions +// +STATIC +EFI_STATUS +WaitForBusBusy ( + VOID + ) +{ + UINTN Retry = 0; + + while (++Retry < MAX_RETRY && (MmioRead16(I2C_STAT) & BB) == 0x1); + + if (Retry == MAX_RETRY) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +PollForStatus( + UINT16 StatusBit + ) +{ + UINTN Retry = 0; + + while(Retry < MAX_RETRY) { + if (MmioRead16(I2C_STAT) & StatusBit) { + //Clear particular status bit from Status register. + MmioOr16(I2C_STAT, StatusBit); + break; + } + Retry++; + } + + if (Retry == MAX_RETRY) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ConfigureI2c ( + VOID + ) +{ + //Program prescaler to obtain 12-MHz clock + MmioWrite16(I2C_PSC, 0x0000); + + //Program SCLL and SCLH + //NOTE: Following values are the register dump after U-Boot code executed. + //We need to figure out how its calculated based on the I2C functional clock and I2C_PSC. + MmioWrite16(I2C_SCLL, 0x0035); + MmioWrite16(I2C_SCLH, 0x0035); + + //Take the I2C controller out of reset. + MmioOr16(I2C_CON, I2C_EN); + + //Initialize the I2C controller. + + //Set I2C controller in Master mode. + MmioOr16(I2C_CON, MST); + + //Enable interrupts for receive/transmit mode. + MmioOr16(I2C_IE, (XRDY_IE | RRDY_IE | ARDY_IE | NACK_IE)); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +I2CReadOneByte ( + UINT8 *Data + ) +{ + EFI_STATUS Status; + + //I2C bus status checking + Status = WaitForBusBusy(); + if (EFI_ERROR(Status)) { + return Status; + } + + //Poll till Receive ready bit is set. + Status = PollForStatus(RRDY); + if (EFI_ERROR(Status)) { + return Status; + } + + *Data = MmioRead8(I2C_DATA); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +I2CWriteOneByte ( + UINT8 Data + ) +{ + EFI_STATUS Status; + + //I2C bus status checking + Status = WaitForBusBusy(); + if (EFI_ERROR(Status)) { + return Status; + } + + //Data transfer + //Poll till Transmit ready bit is set + Status = PollForStatus(XRDY); + if (EFI_ERROR(Status)) { + return Status; + } + + MmioWrite8(I2C_DATA, Data); + + //Wait and check if the NACK is not set. + gBS->Stall(1000); + if (MmioRead16(I2C_STAT) & NACK) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SmbusBlockRead ( + OUT UINT8 *Buffer, + IN UINTN Length + ) +{ + UINTN Index = 0; + EFI_STATUS Status = EFI_SUCCESS; + + //Transfer configuration for receiving data. + MmioWrite16(I2C_CNT, Length); + //Need stop bit before sending data. + MmioWrite16(I2C_CON, (I2C_EN | MST | STP | STT)); + + while (Index < Length) { + //Read a byte + Status = I2CReadOneByte(&Buffer[Index++]); + if (EFI_ERROR(Status)) { + return Status; + } + } + + //Transfer completion + Status = PollForStatus(ARDY); + if (EFI_ERROR(Status)) { + return Status; + } + + return Status; +} + +STATIC +EFI_STATUS +SmbusBlockWrite ( + IN UINT8 *Buffer, + IN UINTN Length + ) +{ + UINTN Index = 0; + EFI_STATUS Status = EFI_SUCCESS; + + //Transfer configuration for transmitting data + MmioWrite16(I2C_CNT, Length); + MmioWrite16(I2C_CON, (I2C_EN | TRX | MST | STT | STP)); + + while (Index < Length) { + //Send a byte + Status = I2CWriteOneByte(Buffer[Index++]); + if (EFI_ERROR(Status)) { + return Status; + } + } + + //Transfer completion + Status = PollForStatus(ARDY); + if (EFI_ERROR(Status)) { + return Status; + } + + return Status; +} + +// +// Public Functions. +// +EFI_STATUS +EFIAPI +SmbusExecute ( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN CONST EFI_SMBUS_DEVICE_COMMAND Command, + IN CONST EFI_SMBUS_OPERATION Operation, + IN CONST BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer + ) +{ + UINT8 *ByteBuffer = Buffer; + EFI_STATUS Status = EFI_SUCCESS; + UINT8 SlaveAddr = (UINT8)(SlaveAddress.SmbusDeviceAddress); + + if (PecCheck) { + return EFI_UNSUPPORTED; + } + + if ((Operation != EfiSmbusWriteBlock) && (Operation != EfiSmbusReadBlock)) { + return EFI_UNSUPPORTED; + } + + //Set the Slave address. + MmioWrite16(I2C_SA, SlaveAddr); + + if (Operation == EfiSmbusReadBlock) { + Status = SmbusBlockRead(ByteBuffer, *Length); + } else if (Operation == EfiSmbusWriteBlock) { + Status = SmbusBlockWrite(ByteBuffer, *Length); + } + + return Status; +} + +EFI_STATUS +EFIAPI +SmbusArpDevice ( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN CONST BOOLEAN ArpAll, + IN CONST EFI_SMBUS_UDID *SmbusUdid OPTIONAL, + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +SmbusGetArpMap ( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN OUT UINTN *Length, + IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ) +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +SmbusNotify ( + IN CONST EFI_SMBUS_HC_PROTOCOL *This, + IN CONST EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN CONST UINTN Data, + IN CONST EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_SMBUS_HC_PROTOCOL SmbusProtocol = +{ + SmbusExecute, + SmbusArpDevice, + SmbusGetArpMap, + SmbusNotify +}; + +EFI_STATUS +InitializeSmbus ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE Handle = NULL; + EFI_STATUS Status; + + //Configure I2C controller. + Status = ConfigureI2c(); + if (EFI_ERROR(Status)) { + DEBUG ((EFI_D_ERROR, "InitializeI2c fails.\n")); + return Status; + } + + // Install the SMBUS interface + Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiSmbusHcProtocolGuid, &SmbusProtocol, NULL); + ASSERT_EFI_ERROR(Status); + + return Status; +} + diff --git a/BeagleBoardPkg/SmbusDxe/Smbus.inf b/BeagleBoardPkg/SmbusDxe/Smbus.inf new file mode 100644 index 0000000000..b13072054a --- /dev/null +++ b/BeagleBoardPkg/SmbusDxe/Smbus.inf @@ -0,0 +1,33 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Smbus + FILE_GUID = d5125e0f-1226-444f-a218-0085996ed5da + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = InitializeSmbus + +[Sources.common] + Smbus.c + +[Packages] + MdePkg/MdePkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + IoLib + +[Guids] + +[Protocols] + gEfiSmbusHcProtocolGuid + +[Pcd] + +[depex] + TRUE
\ No newline at end of file diff --git a/BeagleBoardPkg/TPS65950Dxe/TPS65950.c b/BeagleBoardPkg/TPS65950Dxe/TPS65950.c new file mode 100644 index 0000000000..f47f795a1d --- /dev/null +++ b/BeagleBoardPkg/TPS65950Dxe/TPS65950.c @@ -0,0 +1,116 @@ +/** @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 <TPS65950.h> + +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/EmbeddedExternalDevice.h> +#include <Protocol/SmbusHc.h> + +EFI_SMBUS_HC_PROTOCOL *Smbus; + +EFI_STATUS +Read ( + IN EMBEDDED_EXTERNAL_DEVICE *This, + IN UINTN Register, + IN UINTN Length, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + UINT8 DeviceRegister; + UINTN DeviceRegisterLength = 1; + + SlaveAddress.SmbusDeviceAddress = EXTERNAL_DEVICE_REGISTER_TO_SLAVE_ADDRESS(Register); + DeviceRegister = (UINT8)EXTERNAL_DEVICE_REGISTER_TO_REGISTER(Register); + + //Write DeviceRegister. + Status = Smbus->Execute(Smbus, SlaveAddress, 0, EfiSmbusWriteBlock, FALSE, &DeviceRegisterLength, &DeviceRegister); + if (EFI_ERROR(Status)) { + return Status; + } + + //Read Data + Status = Smbus->Execute(Smbus, SlaveAddress, 0, EfiSmbusReadBlock, FALSE, &Length, Buffer); + return Status; +} + +EFI_STATUS +Write ( + IN EMBEDDED_EXTERNAL_DEVICE *This, + IN UINTN Register, + IN UINTN Length, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + UINT8 DeviceRegister; + UINTN DeviceBufferLength = Length + 1; + UINT8 *DeviceBuffer; + + SlaveAddress.SmbusDeviceAddress = EXTERNAL_DEVICE_REGISTER_TO_SLAVE_ADDRESS(Register); + DeviceRegister = (UINT8)EXTERNAL_DEVICE_REGISTER_TO_REGISTER(Register); + + //Prepare buffer for writing + DeviceBuffer = (UINT8 *)AllocatePool(DeviceBufferLength); + if (DeviceBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto exit; + } + + //Set Device register followed by data to write. + DeviceBuffer[0] = DeviceRegister; + CopyMem(&DeviceBuffer[1], Buffer, Length); + + //Write Data + Status = Smbus->Execute(Smbus, SlaveAddress, 0, EfiSmbusWriteBlock, FALSE, &DeviceBufferLength, DeviceBuffer); + if (EFI_ERROR(Status)) { + goto exit; + } + +exit: + if (DeviceBuffer) { + FreePool(DeviceBuffer); + } + + return Status; +} + +EMBEDDED_EXTERNAL_DEVICE ExternalDevice = { + Read, + Write +}; + +EFI_STATUS +TPS65950Initialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol(&gEfiSmbusHcProtocolGuid, NULL, (VOID **)&Smbus); + ASSERT_EFI_ERROR(Status); + + Status = gBS->InstallMultipleProtocolInterfaces(&ImageHandle, &gEmbeddedExternalDeviceProtocolGuid, &ExternalDevice, NULL); + return Status; +} diff --git a/BeagleBoardPkg/TPS65950Dxe/TPS65950.inf b/BeagleBoardPkg/TPS65950Dxe/TPS65950.inf new file mode 100644 index 0000000000..cc3be3d60a --- /dev/null +++ b/BeagleBoardPkg/TPS65950Dxe/TPS65950.inf @@ -0,0 +1,36 @@ +#%HEADER% +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TPS65950 + FILE_GUID = 71fe861a-5450-48b6-bfb0-b93522616f99 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = TPS65950Initialize + + +[Sources.common] + TPS65950.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + BeagleBoardPkg/BeagleBoardPkg.dec + +[LibraryClasses] + BaseMemoryLib + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + +[Guids] + +[Protocols] + gEfiSmbusHcProtocolGuid + gEmbeddedExternalDeviceProtocolGuid + +[Pcd] + +[depex] + gEfiSmbusHcProtocolGuid diff --git a/BeagleBoardPkg/TimerDxe/Timer.c b/BeagleBoardPkg/TimerDxe/Timer.c new file mode 100644 index 0000000000..32ba09c1eb --- /dev/null +++ b/BeagleBoardPkg/TimerDxe/Timer.c @@ -0,0 +1,239 @@ +/** @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 <Library/OmapLib.h> + +#include <Protocol/Timer.h> +#include <Protocol/HardwareInterrupt.h> +#include <Protocol/TimerDebugSupport.h> + +#include <Omap3530/Omap3530.h> + + +// The notification function to call on every timer interrupt. +volatile EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL; +volatile EFI_PERIODIC_CALLBACK mTimerPeriodicCallback = (EFI_PERIODIC_CALLBACK)NULL; + + +// 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; + +// Cached registers +volatile UINT32 TISR; +volatile UINT32 TCLR; +volatile UINT32 TLDR; +volatile UINT32 TCRR; +volatile UINT32 TIER; + +// Cached interrupt vector +volatile UINTN gVector; + +VOID +EFIAPI +TimerInterruptHandler ( + IN HARDWARE_INTERRUPT_SOURCE Source, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + if (mTimerPeriodicCallback) { + mTimerPeriodicCallback(SystemContext); + } + + if (mTimerNotifyFunction) { + mTimerNotifyFunction(mTimerPeriod); + } + + // Clear all timer interrupts + MmioWrite32(TISR, TISR_CLEAR_ALL); + + // Poll interrupt status bits to ensure clearing + while ((MmioRead32(TISR) & TISR_ALL_INTERRUPT_MASK) != TISR_NO_INTERRUPTS_PENDING); +} + +EFI_STATUS +EFIAPI +TimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ) +{ + if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) { + return EFI_ALREADY_STARTED; + } + + mTimerNotifyFunction = NotifyFunction; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +TimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +{ + EFI_STATUS Status; + UINT64 TimerCount; + INT32 LoadValue; + + if (TimerPeriod == 0) { + // Turn off GPTIMER3 + MmioWrite32(TCLR, TCLR_ST_OFF); + + Status = gInterrupt->DisableInterruptSource(gInterrupt, gVector); + } else { + // Calculate required timer count + TimerCount = DivU64x32(TimerPeriod * 100, PcdGet32(PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds)); + + // Set GPTIMER3 Load register + LoadValue = (INT32) -TimerCount; + MmioWrite32(TLDR, LoadValue); + MmioWrite32(TCRR, LoadValue); + + // Enable Overflow interrupt + MmioWrite32(TIER, TIER_TCAR_IT_DISABLE | TIER_OVF_IT_ENABLE | TIER_MAT_IT_DISABLE); + + // Turn on GPTIMER3, it will reload at overflow + MmioWrite32(TCLR, TCLR_AR_AUTORELOAD | TCLR_ST_ON); + + Status = gInterrupt->EnableInterruptSource(gInterrupt, gVector); + } + + // + // Save the new timer period + // + mTimerPeriod = TimerPeriod; + return Status; +} + +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; +} + +EFI_STATUS +EFIAPI +TimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +TimerDriverRegisterPeriodicCallback ( + IN TIMER_DEBUG_SUPPORT_PROTOCOL *This, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ) +{ + if ((PeriodicCallback == NULL) && (mTimerPeriodicCallback == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((PeriodicCallback != NULL) && (mTimerPeriodicCallback != NULL)) { + return EFI_ALREADY_STARTED; + } + + mTimerPeriodicCallback = PeriodicCallback; + + return EFI_SUCCESS; +} + +EFI_TIMER_ARCH_PROTOCOL gTimer = { + TimerDriverRegisterHandler, + TimerDriverSetTimerPeriod, + TimerDriverGetTimerPeriod, + TimerDriverGenerateSoftInterrupt +}; + +TIMER_DEBUG_SUPPORT_PROTOCOL gTimerDebugSupport = { + TimerDriverRegisterPeriodicCallback +}; + +EFI_STATUS +EFIAPI +TimerInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE Handle = NULL; + EFI_STATUS Status; + UINT32 TimerBaseAddress; + + // Find the interrupt controller protocol. ASSERT if not found. + Status = gBS->LocateProtocol(&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt); + ASSERT_EFI_ERROR (Status); + + // Set up the timer registers + TimerBaseAddress = TimerBase(FixedPcdGet32(PcdBeagleArchTimer)); + TISR = TimerBaseAddress + GPTIMER_TISR; + TCLR = TimerBaseAddress + GPTIMER_TCLR; + TLDR = TimerBaseAddress + GPTIMER_TLDR; + TCRR = TimerBaseAddress + GPTIMER_TCRR; + TIER = TimerBaseAddress + GPTIMER_TIER; + + // Disable the timer + Status = TimerDriverSetTimerPeriod(&gTimer, 0); + ASSERT_EFI_ERROR (Status); + + // Install interrupt handler + gVector = InterruptVectorForTimer(FixedPcdGet32(PcdBeagleArchTimer)); + Status = gInterrupt->RegisterInterruptSource(gInterrupt, gVector, TimerInterruptHandler); + ASSERT_EFI_ERROR (Status); + + // Set up default timer + Status = TimerDriverSetTimerPeriod(&gTimer, FixedPcdGet32(PcdTimerPeriod)); + ASSERT_EFI_ERROR (Status); + + // Install the Timer Architectural Protocol onto a new handle + Status = gBS->InstallMultipleProtocolInterfaces(&Handle, + &gEfiTimerArchProtocolGuid, &gTimer, + &gTimerDebugSupportProtocolGuid, &gTimerDebugSupport, + NULL); + ASSERT_EFI_ERROR(Status); + + return Status; +} + diff --git a/BeagleBoardPkg/TimerDxe/TimerDxe.inf b/BeagleBoardPkg/TimerDxe/TimerDxe.inf new file mode 100644 index 0000000000..b755aa79b4 --- /dev/null +++ b/BeagleBoardPkg/TimerDxe/TimerDxe.inf @@ -0,0 +1,60 @@ +#%HEADER% +#/** @file +# +# Component discription file for Timer module +# +# Copyright (c) 2009, 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 = BeagleBoardTimerDxe + FILE_GUID = 6ddbf08b-cfc9-43cc-9e81-0784ba312ca0 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = TimerInitialize + +[Sources.common] + Timer.c + +[Packages] + BeagleBoardPkg/BeagleBoardPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + +[LibraryClasses] + BaseLib + UefiRuntimeServicesTableLib + PerformanceLib + UefiLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + UefiDriverEntryPoint + IoLib + OmapLib + +[Guids] + +[Protocols] + gEfiTimerArchProtocolGuid + gHardwareInterruptProtocolGuid + gTimerDebugSupportProtocolGuid + +[Pcd.common] + gEmbeddedTokenSpaceGuid.PcdTimerPeriod + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds + gBeagleBoardTokenSpaceGuid.PcdBeagleArchTimer + +[Depex] + gHardwareInterruptProtocolGuid
\ No newline at end of file diff --git a/BeagleBoardPkg/Tools/GNUmakefile b/BeagleBoardPkg/Tools/GNUmakefile new file mode 100644 index 0000000000..2e4e67825e --- /dev/null +++ b/BeagleBoardPkg/Tools/GNUmakefile @@ -0,0 +1,20 @@ +# +# 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. +# + +CC = gcc +CFLAGS = -g + +generate_image: generate_image.c + $(CC) $(CCFLAGS) $(LDFLAGS) -o generate_image generate_image.c + +clean: + rm -f generate_image generate_image.exe diff --git a/BeagleBoardPkg/Tools/generate_image.c b/BeagleBoardPkg/Tools/generate_image.c new file mode 100644 index 0000000000..9bcd67a187 --- /dev/null +++ b/BeagleBoardPkg/Tools/generate_image.c @@ -0,0 +1,410 @@ +/** @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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +//TOC structure as defined by OMAP35XX TRM. +typedef struct { + unsigned int Start; + unsigned int Size; + unsigned int Reserved1; + unsigned int Reserved2; + unsigned int Reserved3; + unsigned char Filename[12]; +} TOC_DATA; + +//NOTE: OMAP3430 TRM has CHSETTINGS and CHRAM structures. +typedef struct { + unsigned int SectionKey; + unsigned char Valid; + unsigned char Version; + unsigned short Reserved; + unsigned int Flags; + unsigned int PRM_CLKSRC_CTRL; + unsigned int PRM_CLKSEL; + unsigned int CM_CLKSEL1_EMU; + unsigned int CM_CLKSEL_CORE; + unsigned int CM_CLKSEL_WKUP; + unsigned int CM_CLKEN_PLL_DPLL3; + unsigned int CM_AUTOIDLE_PLL_DPLL3; + unsigned int CM_CLKSEL1_PLL; + unsigned int CM_CLKEN_PLL_DPLL4; + unsigned int CM_AUTOIDLE_PLL_DPLL4; + unsigned int CM_CLKSEL2_PLL; + unsigned int CM_CLKSEL3_PLL; + unsigned int CM_CLKEN_PLL_MPU; + unsigned int CM_AUTOIDLE_PLL_MPU; + unsigned int CM_CLKSEL1_PLL_MPU; + unsigned int CM_CLKSEL2_PLL_MPU; + unsigned int CM_CLKSTCTRL_MPU; +} CHSETTINGS_DATA; + +typedef struct { + unsigned int SectionKey; + unsigned char Valid; + unsigned char Reserved1; + unsigned char Reserved2; + unsigned char Reserved3; + unsigned short SDRC_SYSCONFIG_LSB; + unsigned short SDRC_CS_CFG_LSB; + unsigned short SDRC_SHARING_LSB; + unsigned short SDRC_ERR_TYPE_LSB; + unsigned int SDRC_DLLA_CTRL; + unsigned short Reserved4; + unsigned short Reserved5; + unsigned int SDRC_POWER; + unsigned short MEMORY_TYPE_CS0; + unsigned short Reserved6; + unsigned int SDRC_MCFG_0; + unsigned short SDRC_MR_0_LSB; + unsigned short SDRC_EMR1_0_LSB; + unsigned short SDRC_EMR2_0_LSB; + unsigned short SDRC_EMR3_0_LSB; + unsigned int SDRC_ACTIM_CTRLA_0; + unsigned int SDRC_ACTIM_CTRLB_0; + unsigned int SDRC_RFRCTRL_0; + unsigned short MEMORY_TYPE_CS1; + unsigned short Reserved7; + unsigned int SDRC_MCFG_1; + unsigned short SDRC_MR_1_LSB; + unsigned short SDRC_EMR1_1_LSB; + unsigned short SDRC_EMR2_1_LSB; + unsigned short SDRC_EMR3_1_LSB; + unsigned int SDRC_ACTIM_CTRLA_1; + unsigned int SDRC_ACTIM_CTRLB_1; + unsigned int SDRC_RFRCTRL_1; + unsigned int Reserved8; + unsigned short Flags; + unsigned short Reserved9; +} CHRAM_DATA; + +#define CHSETTINGS_START 0xA0 +#define CHSETTINGS_SIZE 0x50 +#define CHRAM_START 0xF0 +#define CHRAM_SIZE 0x5C +#define CLOSING_TOC_ITEM_SIZE 4 + +unsigned char gConfigurationHeader[512]; +unsigned int gImageExecutionAddress; +char *gInputImageFile = NULL; +char *gOutputImageFile = NULL; +char *gDataFile = NULL; + +static +void +PrintUsage ( + void + ) +{ + printf("Usage..\n"); +} + +static +void +PopulateCHSETTINGSData ( + FILE *DataFile, + CHSETTINGS_DATA *CHSETTINGSData + ) +{ + unsigned int Value; + + CHSETTINGSData->SectionKey = 0xC0C0C0C1; + CHSETTINGSData->Valid = 0x1; + CHSETTINGSData->Version = 0x1; + CHSETTINGSData->Reserved = 0x00; + CHSETTINGSData->Flags = 0x050001FD; + + //General clock settings. + fscanf(DataFile, "PRM_CLKSRC_CTRL=0x%08x\n", &Value); + CHSETTINGSData->PRM_CLKSRC_CTRL = Value; + fscanf(DataFile, "PRM_CLKSEL=0x%08x\n", &Value); + CHSETTINGSData->PRM_CLKSEL = Value; + fscanf(DataFile, "CM_CLKSEL1_EMU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL1_EMU = Value; + + //Clock configuration + fscanf(DataFile, "CM_CLKSEL_CORE=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL_CORE = Value; + fscanf(DataFile, "CM_CLKSEL_WKUP=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL_WKUP = Value; + + //DPLL3 (Core) settings + fscanf(DataFile, "CM_CLKEN_PLL_DPLL3=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKEN_PLL_DPLL3 = Value; + fscanf(DataFile, "CM_AUTOIDLE_PLL_DPLL3=0x%08x\n", &Value); + CHSETTINGSData->CM_AUTOIDLE_PLL_DPLL3 = Value; + fscanf(DataFile, "CM_CLKSEL1_PLL=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL1_PLL = Value; + + //DPLL4 (Peripheral) settings + fscanf(DataFile, "CM_CLKEN_PLL_DPLL4=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKEN_PLL_DPLL4 = Value; + fscanf(DataFile, "CM_AUTOIDLE_PLL_DPLL4=0x%08x\n", &Value); + CHSETTINGSData->CM_AUTOIDLE_PLL_DPLL4 = Value; + fscanf(DataFile, "CM_CLKSEL2_PLL=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL2_PLL = Value; + fscanf(DataFile, "CM_CLKSEL3_PLL=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL3_PLL = Value; + + //DPLL1 (MPU) settings + fscanf(DataFile, "CM_CLKEN_PLL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKEN_PLL_MPU = Value; + fscanf(DataFile, "CM_AUTOIDLE_PLL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_AUTOIDLE_PLL_MPU = Value; + fscanf(DataFile, "CM_CLKSEL1_PLL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL1_PLL_MPU = Value; + fscanf(DataFile, "CM_CLKSEL2_PLL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSEL2_PLL_MPU = Value; + fscanf(DataFile, "CM_CLKSTCTRL_MPU=0x%08x\n", &Value); + CHSETTINGSData->CM_CLKSTCTRL_MPU = Value; +} + +static +void +PopulateCHRAMData ( + FILE *DataFile, + CHRAM_DATA *CHRAMData + ) +{ + unsigned int Value; + + CHRAMData->SectionKey = 0xC0C0C0C2; + CHRAMData->Valid = 0x1; + + fscanf(DataFile, "SDRC_SYSCONFIG_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_SYSCONFIG_LSB = Value; + fscanf(DataFile, "SDRC_CS_CFG_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_CS_CFG_LSB = Value; + fscanf(DataFile, "SDRC_SHARING_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_SHARING_LSB = Value; + fscanf(DataFile, "SDRC_ERR_TYPE_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_ERR_TYPE_LSB = Value; + fscanf(DataFile, "SDRC_DLLA_CTRL=0x%08x\n", &Value); + CHRAMData->SDRC_DLLA_CTRL = Value; + fscanf(DataFile, "SDRC_POWER=0x%08x\n", &Value); + CHRAMData->SDRC_POWER = Value; + fscanf(DataFile, "MEMORY_TYPE_CS0=0x%04x\n", &Value); + CHRAMData->MEMORY_TYPE_CS0 = Value; + fscanf(DataFile, "SDRC_MCFG_0=0x%08x\n", &Value); + CHRAMData->SDRC_MCFG_0 = Value; + fscanf(DataFile, "SDRC_MR_0_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_MR_0_LSB = Value; + fscanf(DataFile, "SDRC_EMR1_0_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR1_0_LSB = Value; + fscanf(DataFile, "SDRC_EMR2_0_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR2_0_LSB = Value; + fscanf(DataFile, "SDRC_EMR3_0_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR3_0_LSB = Value; + fscanf(DataFile, "SDRC_ACTIM_CTRLA_0=0x%08x\n", &Value); + CHRAMData->SDRC_ACTIM_CTRLA_0 = Value; + fscanf(DataFile, "SDRC_ACTIM_CTRLB_0=0x%08x\n", &Value); + CHRAMData->SDRC_ACTIM_CTRLB_0 = Value; + fscanf(DataFile, "SDRC_RFRCTRL_0=0x%08x\n", &Value); + CHRAMData->SDRC_RFRCTRL_0 = Value; + fscanf(DataFile, "MEMORY_TYPE_CS1=0x%04x\n", &Value); + CHRAMData->MEMORY_TYPE_CS1 = Value; + fscanf(DataFile, "SDRC_MCFG_1=0x%08x\n", &Value); + CHRAMData->SDRC_MCFG_1 = Value; + fscanf(DataFile, "SDRC_MR_1_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_MR_1_LSB = Value; + fscanf(DataFile, "SDRC_EMR1_1_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR1_1_LSB = Value; + fscanf(DataFile, "SDRC_EMR2_1_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR2_1_LSB = Value; + fscanf(DataFile, "SDRC_EMR3_1_LSB=0x%04x\n", &Value); + CHRAMData->SDRC_EMR3_1_LSB = Value; + fscanf(DataFile, "SDRC_ACTIM_CTRLA_1=0x%08x\n", &Value); + CHRAMData->SDRC_ACTIM_CTRLA_1 = Value; + fscanf(DataFile, "SDRC_ACTIM_CTRLB_1=0x%08x\n", &Value); + CHRAMData->SDRC_ACTIM_CTRLB_1 = Value; + fscanf(DataFile, "SDRC_RFRCTRL_1=0x%08x\n", &Value); + CHRAMData->SDRC_RFRCTRL_1 = Value; + + CHRAMData->Flags = 0x0003; +} + +static +void +PrepareConfigurationHeader ( + void + ) +{ + TOC_DATA Toc; + CHSETTINGS_DATA CHSETTINGSData; + CHRAM_DATA CHRAMData; + unsigned int ConfigurationHdrOffset = 0; + FILE *DataFile; + + // Open data file + DataFile = fopen(gDataFile, "rb"); + if (DataFile == NULL) { + fprintf(stderr, "Can't open data file %s.\n", gOutputImageFile); + exit(1); + } + + //Initialize configuration header. + memset(gConfigurationHeader, 0x00, sizeof(gConfigurationHeader)); + + //CHSETTINGS TOC + memset(&Toc, 0x00, sizeof(TOC_DATA)); + Toc.Start = CHSETTINGS_START; + Toc.Size = CHSETTINGS_SIZE; + strcpy((char *)Toc.Filename, (const char *)"CHSETTINGS"); + memcpy(gConfigurationHeader + ConfigurationHdrOffset, &Toc, sizeof(TOC_DATA)); + + //Populate CHSETTINGS Data + memset(&CHSETTINGSData, 0x00, sizeof(CHSETTINGS_DATA)); + PopulateCHSETTINGSData(DataFile, &CHSETTINGSData); + memcpy(gConfigurationHeader + Toc.Start, &CHSETTINGSData, Toc.Size); + + //Adjust ConfigurationHdrOffset to point to next TOC + ConfigurationHdrOffset += sizeof(TOC_DATA); + + //CHRAM TOC + memset(&Toc, 0x00, sizeof(TOC_DATA)); + Toc.Start = CHRAM_START; + Toc.Size = CHRAM_SIZE; + strcpy((char *)Toc.Filename, (const char *)"CHRAM"); + memcpy(gConfigurationHeader + ConfigurationHdrOffset, &Toc, sizeof(TOC_DATA)); + + //Populate CHRAM Data + memset(&CHRAMData, 0x00, sizeof(CHRAM_DATA)); + PopulateCHRAMData(DataFile, &CHRAMData); + memcpy(gConfigurationHeader + Toc.Start, &CHRAMData, Toc.Size); + + //Adjust ConfigurationHdrOffset to point to next TOC + ConfigurationHdrOffset += sizeof(TOC_DATA); + + //Closing TOC item + memset(gConfigurationHeader + ConfigurationHdrOffset, 0xFF, CLOSING_TOC_ITEM_SIZE); + ConfigurationHdrOffset += CLOSING_TOC_ITEM_SIZE; + + // Close data file + fclose(DataFile); +} + +static +void +ConstructImage ( + void + ) +{ + FILE *InputFile; + FILE *OutputFile; + unsigned int InputImageFileSize; + unsigned int NewImageFileSize; + struct stat FileStat; + char Ch; + unsigned int i; + + InputFile = fopen(gInputImageFile, "rb"); + if (InputFile == NULL) { + fprintf(stderr, "Can't open input file.\n"); + exit(0); + } + + //Get the size of the input image. + fstat(fileno(InputFile), &FileStat); + InputImageFileSize = FileStat.st_size; + + //Calculate new file size + NewImageFileSize = InputImageFileSize - 520; + + OutputFile = fopen(gOutputImageFile, "wb"); + if (OutputFile == NULL) { + fprintf(stderr, "Can't open output file %s.\n", gOutputImageFile); + exit(0); + } + + //Write Configuration header + fwrite(gConfigurationHeader, 1, sizeof(gConfigurationHeader), OutputFile); + + //Write image header (Input image size, execution address) + fwrite(&NewImageFileSize, 1, 4, OutputFile); + fwrite(&gImageExecutionAddress, 1, 4, OutputFile); + + //Skip first 0x207 bytes + fseek(InputFile, 520, SEEK_SET); + + //Copy input image to the output file. + for (i = 0; i < NewImageFileSize; i++) { + fread(&Ch, 1, 1, InputFile); + fwrite(&Ch, 1, 1, OutputFile); + } + + fclose(InputFile); + fclose(OutputFile); +} + +int +main ( + int argc, + char** argv + ) +{ + char Ch; + unsigned char *ptr; + + if (argc == 1) { + PrintUsage (); + exit(1); + } + + while ((Ch = getopt(argc, argv, "D:E:I:O:")) != -1) { + switch (Ch) { + case 'E': /* Image execution address */ + gImageExecutionAddress = strtoul (optarg, (char **)&ptr, 16); + break; + + case 'I': /* Input image file */ + gInputImageFile = optarg; + break; + + case 'O': /* Output image file */ + gOutputImageFile = optarg; + break; + + case 'D': /* Data file */ + gDataFile = optarg; + break; + + case '?': + if ((optopt == 'E') || (optopt == 'I') || (optopt == 'O')) { + fprintf (stderr, "Option -%c requires an argument.\n", optopt); + } else if (isprint (optopt)) { + fprintf (stderr, "Unknown option `-%c'.\n", optopt); + } else { + fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); + } + return 1; + + default: + abort (); + } + } + + //Prepare configuration header + PrepareConfigurationHeader (); + + //Build image with configuration header + image header + image + ConstructImage (); + + return 0; +} diff --git a/BeagleBoardPkg/build.sh b/BeagleBoardPkg/build.sh new file mode 100755 index 0000000000..94cabbe623 --- /dev/null +++ b/BeagleBoardPkg/build.sh @@ -0,0 +1,127 @@ +#!/bin/bash +# 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. +# + +set -e +shopt -s nocasematch + +function process_debug_scripts { + if [[ -d $1 ]]; then + for filename in `ls $1` + do + sed -e "s@ZZZZZZ@$BUILD_ROOT@g" -e "s@WWWWWW@$WORKSPACE@g" \ + "$1/$filename" \ + > "$BUILD_ROOT/$filename" + + #For ARMCYGWIN, we have to change /cygdrive/c to c: + if [[ $TARGET_TOOLS == RVCT31CYGWIN ]] + then + mv "$BUILD_ROOT/$filename" "$BUILD_ROOT/$filename"_temp + sed -e "s@/cygdrive/\(.\)@\1:@g" \ + "$BUILD_ROOT/$filename"_temp \ + > "$BUILD_ROOT/$filename" + rm -f "$BUILD_ROOT/$filename"_temp + fi + done + fi +} + + +# +# Setup workspace if it is not set +# +if [ -z "$WORKSPACE" ] +then + echo Initializing workspace + cd .. + export EDK_TOOLS_PATH=`pwd`/BaseTools + source edksetup.sh BaseTools +else + echo Building from: $WORKSPACE +fi + +# +# Pick a default tool type for a given OS +# +case `uname` in + CYGWIN*) + TARGET_TOOLS=RVCT31CYGWIN + ;; + Linux*) + # Not tested + TARGET_TOOLS=ELFGCC + ;; + Darwin*) + Major=$(uname -r | cut -f 1 -d '.') + if [[ $Major == 9 ]] + then + # Not supported by this open source project + TARGET_TOOLS=XCODE31 + else + TARGET_TOOLS=XCODE32 + fi + ;; +esac + +BUILD_ROOT=$WORKSPACE/Build/BeagleBoard/DEBUG_"$TARGET_TOOLS" +GENERATE_IMAGE=$WORKSPACE/BeagleBoardPkg/Tools/generate_image +FLASH_BOOT=$BUILD_ROOT/FV/BeagleBoard_EFI_flashboot.fd + +if [[ ! -f `which build` || ! -f `which GenFv` ]]; +then + # build the tools if they don't yet exist + echo Building tools + make -C $WORKSPACE/BaseTools +else + echo using prebuilt tools +fi + +# +# Build the edk2 BeagleBoard code +# +build -p $WORKSPACE/BeagleBoardPkg/BeagleBoardPkg.dsc -a ARM -t $TARGET_TOOLS $1 $2 $3 $4 $5 $6 $7 $8 + +for arg in "$@" +do + if [[ $arg == clean ]]; then + # no need to post process if we are doing a clean + exit + elif [[ $arg == cleanall ]]; then + make -C BaseTools/ clean + make -C $WORKSPACE/BeagleBoardPkg/Tools clean + exit + + fi +done + + +# +# Build the tool used to patch the FLASH image to work with the Beagle board ROM +# +if [[ ! -e $GENERATE_IMAGE ]]; +then + make -C $WORKSPACE/BeagleBoardPkg/Tools +fi + +echo Patching FD to work with BeagleBoard ROM +rm -f $FLASH_BOOT + +# +# Ram starts at 0x80000000 +# OMAP 3530 TRM defines 0x80008208 as the entry point +# The reset vector is caught by the mask ROM in the OMAP 3530 so that is why this entry +# point looks so strange. +# OMAP 3430 TRM section 26.4.8 has Image header information. (missing in OMAP 3530 TRM) +# +$GENERATE_IMAGE -D $WORKSPACE/BeagleBoardPkg/ConfigurationHeader.dat -E 0x80008208 -I $BUILD_ROOT/FV/BEAGLEBOARD_EFI.fd -O $FLASH_BOOT + +echo Creating debugger scripts +process_debug_scripts $WORKSPACE/BeagleBoardPkg/Debugger_scripts + diff --git a/BeagleBoardPkg/readme.txt b/BeagleBoardPkg/readme.txt new file mode 100644 index 0000000000..8234fead73 --- /dev/null +++ b/BeagleBoardPkg/readme.txt @@ -0,0 +1,11 @@ +Build:
+======
+Build requires a bash script.
+./build.sh.
+
+FAQ:
+====
+If you get a build error 000E: File/directory not found FatPkg/EnhancedFat/FatDxe/FatDxe.inf
+
+cd $WORKSPACE
+svn checkout https://fat-driver2.tianocore.org/svn/fat-driver2/trunk/FatPkg FatPkg --username username
\ No newline at end of file diff --git a/EmbeddedPkg/DebugSupportDxe/DebugSupport.c b/EmbeddedPkg/DebugSupportDxe/DebugSupport.c new file mode 100644 index 0000000000..26f4c387dc --- /dev/null +++ b/EmbeddedPkg/DebugSupportDxe/DebugSupport.c @@ -0,0 +1,119 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/DebugSupport.h>
+#include <Protocol/TimerDebugSupport.h>
+
+EFI_STATUS
+EFIAPI
+DebugSupportGetMaximumProcessorIndex (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ OUT UINTN *MaxProcessorIndex
+ )
+{
+ if (MaxProcessorIndex == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *MaxProcessorIndex = 0;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+DebugSupportRegisterPeriodicCallback (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN EFI_PERIODIC_CALLBACK PeriodicCallback
+ )
+{
+ TIMER_DEBUG_SUPPORT_PROTOCOL *Timer;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol(&gTimerDebugSupportProtocolGuid, NULL, (VOID **)&Timer);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = Timer->RegisterPeriodicCallback(Timer, PeriodicCallback);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DebugSupportRegisterExceptionCallback (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN EFI_EXCEPTION_CALLBACK ExceptionCallback,
+ IN EFI_EXCEPTION_TYPE ExceptionType
+ )
+{
+ EFI_CPU_ARCH_PROTOCOL *Cpu;
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = Cpu->RegisterInterruptHandler(Cpu, ExceptionType, (EFI_CPU_INTERRUPT_HANDLER)ExceptionCallback);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+DebugSupportInvalidateInstructionCache (
+ IN EFI_DEBUG_SUPPORT_PROTOCOL *This,
+ IN UINTN ProcessorIndex,
+ IN VOID *Start,
+ IN UINT64 Length
+ )
+{
+ InvalidateInstructionCacheRange(Start, Length);
+ return EFI_SUCCESS;
+}
+
+EFI_DEBUG_SUPPORT_PROTOCOL mDebugSupport = {
+ IsaArm,
+ DebugSupportGetMaximumProcessorIndex,
+ DebugSupportRegisterPeriodicCallback,
+ DebugSupportRegisterExceptionCallback,
+ DebugSupportInvalidateInstructionCache
+};
+
+EFI_STATUS
+DebugSupportDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = NULL;
+
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiDebugSupportProtocolGuid);
+ Status = gBS->InstallMultipleProtocolInterfaces(&Handle, &gEfiDebugSupportProtocolGuid, &mDebugSupport, NULL);
+
+ return Status;
+}
+
diff --git a/EmbeddedPkg/DebugSupportDxe/DebugSupportDxe.inf b/EmbeddedPkg/DebugSupportDxe/DebugSupportDxe.inf new file mode 100644 index 0000000000..d3dab66ab7 --- /dev/null +++ b/EmbeddedPkg/DebugSupportDxe/DebugSupportDxe.inf @@ -0,0 +1,28 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmDebugSupportDxe
+ FILE_GUID = 2e7c151b-cbd8-4df6-a0e3-cde660067c6a
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = DebugSupportDxeInitialize
+
+[Sources.common]
+ DebugSupport.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedePkg/EmbeddedePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ CacheMaintenanceLib
+ UefiDriverEntryPoint
+ ArmLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+ gEfiDebugSupportProtocolGuid
+ gTimerDebugSupportProtocolGuid
+
diff --git a/EmbeddedPkg/Ebl/CmdTemplate.c b/EmbeddedPkg/Ebl/CmdTemplate.c new file mode 100644 index 0000000000..456c4afe72 --- /dev/null +++ b/EmbeddedPkg/Ebl/CmdTemplate.c @@ -0,0 +1,65 @@ +/** @file
+ %CommandName% for EBL (Embedded Boot Loader)
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: CmdTemplate.c
+
+ Search/Replace %CommandName% with the name of your new command
+
+**/
+
+#include "Ebl.h"
+
+
+/**
+ Fill Me In
+
+ Argv[0] - "%CommandName%"
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+Ebl%CommandName%Cmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmd%CommandName%Template[] =
+{
+ {
+ "%CommandName%",
+ " [show args] ; explain args and command",
+ NULL,
+ Ebl%CommandName%Cmd
+ }
+};
+
+
+/**
+ Initialize the commands in this in this file
+**/
+VOID
+EblInitialize%CommandName%Cmd (
+ VOID
+ )
+{
+ EblAddCommands (mCmd%CommandName%Template, sizeof (mCmd%CommandName%Template)/sizeof (EBL_COMMAND_TABLE));
+}
+
diff --git a/EmbeddedPkg/Ebl/Command.c b/EmbeddedPkg/Ebl/Command.c new file mode 100644 index 0000000000..7899a0f442 --- /dev/null +++ b/EmbeddedPkg/Ebl/Command.c @@ -0,0 +1,978 @@ +/** @file
+ Basic commands and command processing infrastructure for EBL
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Ebl.h"
+#include <Protocol/DiskIo.h>
+#include <Protocol/BlockIo.h>
+
+UINTN mCmdTableMaxIndex = EBL_MAX_COMMAND_COUNT;
+UINTN mCmdTableNextFreeIndex = 0;
+EBL_COMMAND_TABLE *mCmdTable[EBL_MAX_COMMAND_COUNT];
+
+/**
+ Converts a lowercase Ascii character to upper one
+
+ If Chr is lowercase Ascii character, then converts it to upper one.
+
+ If Value >= 0xA0, then ASSERT().
+ If (Value & 0x0F) >= 0x0A, then ASSERT().
+
+ @param chr one Ascii character
+
+ @return The uppercase value of Ascii character
+
+**/
+STATIC
+CHAR8
+AsciiToUpper (
+ IN CHAR8 Chr
+ )
+{
+ return (UINT8) ((Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr);
+}
+
+
+/**
+ Case insensitve comparison of two Null-terminated Unicode strings with maximum
+ lengths, and returns the difference between the first mismatched Unicode
+ characters.
+ This function compares the Null-terminated Unicode string FirstString to the
+ Null-terminated Unicode string SecondString. At most, Length Unicode
+ characters will be compared. If Length is 0, then 0 is returned. If
+ FirstString is identical to SecondString, then 0 is returned. Otherwise, the
+ value returned is the first mismatched Unicode character in SecondString
+ subtracted from the first mismatched Unicode character in FirstString.
+
+ @param FirstString Pointer to a Null-terminated ASCII string.
+ @param SecondString Pointer to a Null-terminated ASCII string.
+ @param Length Max length to compare.
+
+ @retval 0 FirstString is identical to SecondString using case insensitive
+ comparisons.
+ @retval !=0 FirstString is not identical to SecondString using case
+ insensitive comparisons.
+
+**/
+INTN
+EFIAPI
+AsciiStrniCmp (
+ IN CONST CHAR8 *FirstString,
+ IN CONST CHAR8 *SecondString,
+ IN UINTN Length
+ )
+{
+ if (Length == 0) {
+ return 0;
+ }
+
+ while ((AsciiToUpper (*FirstString) != '\0') &&
+ (AsciiToUpper (*FirstString) == AsciiToUpper (*SecondString)) &&
+ (Length > 1)) {
+ FirstString++;
+ SecondString++;
+ Length--;
+ }
+
+ return AsciiToUpper (*FirstString) - AsciiToUpper (*SecondString);
+}
+
+
+
+/**
+ Add a command to the mCmdTable. If there is no free space in the command
+ table ASSERT. The mCmdTable is maintained in alphabetical order and the
+ new entry is inserted into its sorted possition.
+
+ @param Entry Commnad Entry to add to the CmdTable
+
+**/
+VOID
+EFIAPI
+EblAddCommand (
+ IN const EBL_COMMAND_TABLE *Entry
+ )
+{
+ UINTN Count;
+
+ if (mCmdTableNextFreeIndex == EBL_MAX_COMMAND_COUNT) {
+ //
+ // Ran out of space to store commands. Increase EBL_MAX_COMMAND_COUNT
+ //
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Add command and Insertion sort array in the process
+ //
+ mCmdTable[mCmdTableNextFreeIndex] = (EBL_COMMAND_TABLE *)Entry;
+ if (mCmdTableNextFreeIndex != 0) {
+ for (Count = mCmdTableNextFreeIndex; Count > 0; Count--) {
+ if (AsciiStriCmp (mCmdTable[Count - 1]->Name, Entry->Name) <= 0) {
+ break;
+ }
+
+ mCmdTable[Count] = mCmdTable[Count - 1];
+ }
+ mCmdTable[Count] = (EBL_COMMAND_TABLE *)Entry;
+ }
+
+ mCmdTableNextFreeIndex++;
+}
+
+
+/**
+ Add an set of commands to the command table. Most commonly used on static
+ array of commands.
+
+ @param EntryArray Pointer to array of command entries
+ @param ArrayCount Number of commnad entries to add
+
+**/
+VOID
+EFIAPI
+EblAddCommands (
+ IN const EBL_COMMAND_TABLE *EntryArray,
+ IN UINTN ArrayCount
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < ArrayCount; Index++) {
+ EblAddCommand (&EntryArray[Index]);
+ }
+}
+
+
+EBL_ADD_COMMAND_PROTOCOL gEblAddCommand = {
+ EblAddCommand,
+ EblAddCommands,
+ EblGetCharKey,
+ EblAnyKeyToContinueQtoQuit
+};
+
+
+
+/**
+ Return the best matching command for the passed in command name. The match
+ does not have to be exact, it just needs to be unqiue. This enables commands
+ to be shortend to the smallest set of starting characters that is unique.
+
+ @param CommandName Name of command to search for
+
+ @return NULL CommandName did not match or was not unique
+ Other Pointer to EBL_COMMAND_TABLE entry for CommandName
+
+**/
+EBL_COMMAND_TABLE *
+EblGetCommand (
+ IN CHAR8 *CommandName
+ )
+{
+ UINTN Index;
+ UINTN BestMatchCount;
+ UINTN Length;
+ EBL_COMMAND_TABLE *Match;
+
+ Length = AsciiStrLen (CommandName);
+ for (Index = 0, BestMatchCount = 0, Match = NULL; Index < mCmdTableNextFreeIndex; Index++) {
+ if (AsciiStriCmp (mCmdTable[Index]->Name, CommandName) == 0) {
+ // match a command exactly
+ return mCmdTable[Index];
+ }
+
+ if (AsciiStrniCmp (CommandName, mCmdTable[Index]->Name, Length) == 0) {
+ // partial match, so keep looking to make sure there is only one partial match
+ BestMatchCount++;
+ Match = mCmdTable[Index];
+ }
+ }
+
+ if (BestMatchCount == 1) {
+ return Match;
+ }
+
+ //
+ // We had no matches or too many matches
+ //
+ return NULL;
+}
+
+
+
+/**
+ List out help information on all the commands or print extended information
+ about a specific passed in command.
+
+ Argv[0] - "help"
+ Argv[1] - Command to display help about
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblHelpCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINTN Index;
+ CHAR8 *Ptr;
+ UINTN CurrentRow;
+
+ if (Argc == 1) {
+ // Print all the commands
+ AsciiPrint ("Embedded Boot Loader (EBL) commands (help command for more info):\n");
+ for (Index = 0; Index < mCmdTableNextFreeIndex; Index++) {
+ EblSetTextColor (EFI_YELLOW);
+ AsciiPrint (" %a", mCmdTable[Index]->Name);
+ EblSetTextColor (0);
+ AsciiPrint ("%a\n", mCmdTable[Index]->HelpSummary);
+ }
+ } else if (Argv[1] != NULL) {
+ // Print specific help
+ for (Index = 0, CurrentRow = 0; Index < mCmdTableNextFreeIndex; Index++) {
+ if (AsciiStriCmp (Argv[1], mCmdTable[Index]->Name) == 0) {
+ Ptr = (mCmdTable[Index]->Help == NULL) ? mCmdTable[Index]->HelpSummary : mCmdTable[Index]->Help;
+ AsciiPrint ("%a%a\n", Argv[1], Ptr);
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
+ break;
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Exit the EBL. If the commnad processor sees EFI_ABORTED return status it will
+ exit the EBL.
+
+ Argv[0] - "exit"
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_ABORTED
+
+**/
+EFI_STATUS
+EblExitCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status; + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + UINTN MapKey; + UINTN DescriptorSize; + UINTN DescriptorVersion; + UINTN Pages; +
+ if (Argc > 1) {
+ if (AsciiStriCmp (Argv[1], "efi") != 0) {
+ return EFI_ABORTED;
+ }
+ } else if (Argc == 1) {
+ return EFI_ABORTED;
+ }
+
+ MemoryMap = NULL; + MemoryMapSize = 0; + do { + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + + Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1; + MemoryMap = AllocatePages (Pages); + + // + // Get System MemoryMap + // + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + // Don't do anything between the GetMemoryMap() and ExitBootServices() + if (!EFI_ERROR (Status)) { + Status = gBS->ExitBootServices (gImageHandle, MapKey); + if (EFI_ERROR (Status)) { + FreePages (MemoryMap, Pages); + MemoryMap = NULL; + MemoryMapSize = 0; + } + } + } + } while (EFI_ERROR (Status)); +
+ //
+ // At this point it is very dangerous to do things EFI as most of EFI is now gone.
+ // This command is useful if you are working with a debugger as it will shutdown
+ // DMA and other things that could break a soft resets.
+ //
+ CpuDeadLoop ();
+
+ // Should never get here, but makes the compiler happy
+ return EFI_ABORTED;
+}
+
+
+/**
+ Update the screen by decrementing the timeout value.
+ This AsciiPrint has to match the AsciiPrint in
+ EblPauseCmd.
+
+ @param ElaspedTime Current timout value remaining
+
+**/
+VOID
+EFIAPI
+EblPauseCallback (
+ IN UINTN ElapsedTime
+ )
+{
+ AsciiPrint ("\b\b\b\b\b\b\b\b\b\b\b\b \b\b%3d seconds", ElapsedTime);
+}
+
+/**
+ Pause until a key is pressed and abort the remaining commands on the command
+ line. If no key is pressed continue processing the command line. This command
+ allows the user to stop an operation from happening and return control to the
+ command prompt.
+
+ Argv[0] - "pause"
+ Argv[1] - timeout value is decimal seconds
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS Timeout expired with no input
+ @return EFI_TIMEOUT Stop procesing other commands on the same command line
+
+**/
+EFI_STATUS
+EblPauseCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ UINTN Delay;
+ EFI_INPUT_KEY Key;
+
+ Delay = (Argc == 1)? 10 : AsciiStrDecimalToUintn (Argv[1]);
+
+ AsciiPrint ("Hit any key to break. You have %3d seconds", Delay);
+ Status = EblGetCharKey (&Key, Delay, EblPauseCallback);
+ AsciiPrint ("\n");
+
+ // If we timeout then the pause succeded thus return success
+ // If we get a key return timout to stop other commnad on this cmd line
+ return (Status == EFI_SUCCESS) ? EFI_TIMEOUT : EFI_SUCCESS;;
+}
+
+
+/**
+ On a debug build issue a software breakpoint to enter the debugger
+
+ Argv[0] - "break"
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblBreakPointCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ CpuBreakpoint ();
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reset the system. If no Argument do a Cold reset. If argument use that reset type
+ (W)arm = Warm Reset
+ (S)hutdown = Shutdown Reset
+
+ Argv[0] - "reset"
+ Argv[1] - warm or shutdown reset type
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblResetCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_RESET_TYPE ResetType;
+
+ ResetType = EfiResetCold;
+ if (Argc > 1) {
+ switch (*Argv[1]) {
+ case 'W':
+ case 'w':
+ ResetType = EfiResetWarm;
+ break;
+ case 'S':
+ case 's':
+ ResetType = EfiResetShutdown;
+ }
+ }
+
+ gRT->ResetSystem (ResetType, EFI_SUCCESS, 0, NULL);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Toggle page break global. This turns on and off prompting to Quit or hit any
+ key to continue when a command is about to scroll the screen with its output
+
+ Argv[0] - "page"
+ Argv[1] - on or off
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblPageCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ if (Argc <= 1) {
+ // toggle setting
+ gPageBreak = (gPageBreak) ? FALSE : TRUE;
+ } else {
+ // use argv to set the value
+ if ((Argv[1][0] == 'o') || (Argv[1][0] == 'O')) {
+ if ((Argv[1][1] == 'n') || (Argv[1][1] == 'N')) {
+ gPageBreak = TRUE;
+ } else if ((Argv[1][1] == 'f') || (Argv[1][1] == 'F')) {
+ gPageBreak = FALSE;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EblSleepCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINTN Delay;
+
+ Delay = (Argc == 1)? 10 : AsciiStrDecimalToUintn (Argv[1]);
+
+ gBS->Stall (Delay * 1000000);
+
+ return EFI_SUCCESS;
+}
+
+CHAR8
+ConvertToTextLine (
+ IN CHAR8 Character
+ )
+{
+ if (Character < ' ' || Character > '~')
+ {
+ return '.';
+ }
+ else
+ {
+ return Character;
+ }
+}
+
+UINTN
+GetBytes (
+ IN UINT8 *Address,
+ IN UINTN Bytes
+ )
+{
+ UINTN Result = 0;
+
+ if (Bytes >= 1)
+ Result = *Address++;
+
+ if (Bytes >= 2)
+ Result = (Result << 8) + *Address++;
+
+ if (Bytes >= 3)
+ Result = (Result << 8) + *Address++;
+
+ return Result;
+}
+
+CHAR8 mBlanks[] = " ";
+
+EFI_STATUS
+OutputData (
+ IN UINT8 *Address,
+ IN UINTN Length,
+ IN UINTN Width,
+ IN UINTN Offset
+ )
+{
+ UINT8 *EndAddress;
+ UINTN Line;
+ CHAR8 TextLine[0x11];
+ UINTN CurrentRow = 0;
+ UINTN Bytes;
+ UINTN Spaces = 0;
+ CHAR8 Blanks[80];
+
+ AsciiStrCpy (Blanks, mBlanks);
+ for (EndAddress = Address + Length; Address < EndAddress; Offset += Line)
+ {
+ AsciiPrint ("%08x: ", Offset);
+ for (Line = 0; (Line < 0x10) && (Address < EndAddress);)
+ {
+ Bytes = EndAddress - Address;
+
+ switch (Width)
+ {
+ case 4:
+ if (Bytes >= 4)
+ {
+ AsciiPrint ("%08x ", *((UINT32 *)Address));
+ TextLine[Line++] = ConvertToTextLine(*Address++);
+ TextLine[Line++] = ConvertToTextLine(*Address++);
+ TextLine[Line++] = ConvertToTextLine(*Address++);
+ TextLine[Line++] = ConvertToTextLine(*Address++);
+ }
+ else
+ {
+ AsciiPrint ("%08x ", GetBytes(Address, Bytes));
+ Address += Bytes;
+ Line += Bytes;
+ }
+ break;
+
+ case 2:
+ if (Bytes >= 2)
+ {
+ AsciiPrint ("%04x ", *((UINT16 *)Address));
+ TextLine[Line++] = ConvertToTextLine(*Address++);
+ TextLine[Line++] = ConvertToTextLine(*Address++);
+ }
+ else
+ {
+ AsciiPrint ("%04x ", GetBytes(Address, Bytes));
+ Address += Bytes;
+ Line += Bytes;
+ }
+ break;
+
+ case 1:
+ AsciiPrint ("%02x ", *((UINT8 *)Address));
+ TextLine[Line++] = ConvertToTextLine(*Address++);
+ break;
+
+ default:
+ AsciiPrint ("Width must be 1, 2, or 4!\n");
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ // Pad spaces
+ if (Line < 0x10)
+ {
+ switch (Width)
+ {
+ case 4:
+ Spaces = 9 * ((0x10 - Line)/4);
+ break;
+ case 2:
+ Spaces = 5 * ((0x10 - Line)/2);
+ break;
+ case 1:
+ Spaces = 3 * (0x10 - Line);
+ break;
+ }
+
+ Blanks[Spaces] = '\0';
+
+ AsciiPrint(Blanks);
+
+ Blanks[Spaces] = ' ';
+ }
+
+ TextLine[Line] = 0;
+ AsciiPrint ("|%a|\n", TextLine);
+
+ if (EblAnyKeyToContinueQtoQuit(&CurrentRow, FALSE))
+ {
+ return EFI_END_OF_FILE;
+ }
+ }
+
+ if (Length % Width != 0)
+ {
+ AsciiPrint ("%08x\n", Offset);
+ }
+
+ return EFI_SUCCESS;
+}
+
+#define HEXDUMP_CHUNK 1024
+
+EFI_STATUS
+EblHexdumpCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_OPEN_FILE *File;
+ VOID *Location;
+ UINTN Size;
+ UINTN Width = 1;
+ UINTN Offset = 0;
+ EFI_STATUS Status;
+ UINTN Chunk = HEXDUMP_CHUNK;
+
+ if ((Argc < 2) || (Argc > 3))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Argc == 3)
+ {
+ Width = AsciiStrDecimalToUintn(Argv[2]);
+ }
+
+ if ((Width != 1) && (Width != 2) && (Width != 4))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ File = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);
+ if (File == NULL)
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ Location = AllocatePool(Chunk);
+ Size = EfiTell(File, NULL);
+
+ for (Offset = 0; Offset + HEXDUMP_CHUNK <= Size; Offset += Chunk)
+ {
+ Chunk = HEXDUMP_CHUNK;
+
+ Status = EfiRead(File, Location, &Chunk);
+ if (EFI_ERROR(Status))
+ {
+ AsciiPrint ("Error reading file content\n");
+ goto Exit;
+ }
+
+ Status = OutputData(Location, Chunk, Width, File->BaseOffset + Offset);
+ if (EFI_ERROR(Status))
+ {
+ if (Status == EFI_END_OF_FILE) {
+ Status = EFI_SUCCESS;
+ }
+ goto Exit;
+ }
+ }
+
+ // Any left over?
+ if (Offset < Size)
+ {
+ Chunk = Size - Offset;
+ Status = EfiRead(File, Location, &Chunk);
+ if (EFI_ERROR(Status))
+ {
+ AsciiPrint ("Error reading file content\n");
+ goto Exit;
+ }
+
+ Status = OutputData(Location, Chunk, Width, File->BaseOffset + Offset);
+ if (EFI_ERROR(Status))
+ {
+ if (Status == EFI_END_OF_FILE) {
+ Status = EFI_SUCCESS;
+ }
+ goto Exit;
+ }
+ }
+
+Exit:
+ EfiClose(File);
+
+ FreePool(Location);
+
+ return EFI_SUCCESS;
+}
+
+#define USE_DISKIO 1
+
+EFI_STATUS
+EblDiskIoCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ UINTN Offset;
+ UINT8 *EndOffset;
+ UINTN Length;
+ UINTN Line;
+ UINT8 *Buffer;
+ UINT8 *BufferOffset;
+ CHAR8 TextLine[0x11];
+#if USE_DISKIO
+ EFI_DISK_IO_PROTOCOL *DiskIo;
+#else
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ UINTN Lba;
+#endif
+
+ if (AsciiStrCmp(Argv[1], "r") == 0)
+ {
+ Offset = AsciiStrHexToUintn(Argv[2]);
+ Length = AsciiStrHexToUintn(Argv[3]);
+
+#if USE_DISKIO
+ Status = gBS->LocateProtocol(&gEfiDiskIoProtocolGuid, NULL, (VOID **)&DiskIo);
+ if (EFI_ERROR(Status))
+ {
+ AsciiPrint("Did not locate DiskIO\n");
+ return Status;
+ }
+
+ Buffer = AllocatePool(Length);
+ BufferOffset = Buffer;
+
+ Status = DiskIo->ReadDisk(DiskIo, SIGNATURE_32('f','l','s','h'), Offset, Length, Buffer);
+ if (EFI_ERROR(Status))
+ {
+ AsciiPrint("DiskIO read failed\n");
+ gBS->FreePool(Buffer);
+ return Status;
+ }
+#else
+ Status = gBS->LocateProtocol(&gEfiBlockIoProtocolGuid, NULL, (VOID **)&BlockIo);
+ if (EFI_ERROR(Status))
+ {
+ AsciiPrint("Did not locate BlockIo\n");
+ return Status;
+ }
+
+ Length = BlockIo->Media->BlockSize;
+ Buffer = AllocatePool(Length);
+ BufferOffset = Buffer;
+ Lba = Offset/BlockIo->Media->BlockSize;
+
+ Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, Lba, Length, Buffer);
+ if (EFI_ERROR(Status))
+ {
+ AsciiPrint("BlockIo read failed\n");
+ gBS->FreePool(Buffer);
+ return Status;
+ }
+
+ // Whack offset to what we actually read from
+ Offset = Lba * BlockIo->Media->BlockSize;
+
+ Length = 0x100;
+#endif
+
+ for (EndOffset = BufferOffset + Length; BufferOffset < EndOffset; Offset += 0x10)
+ {
+ AsciiPrint ("%08x: ", Offset);
+
+ for (Line = 0; Line < 0x10; Line++)
+ {
+ AsciiPrint ("%02x ", *BufferOffset);
+
+ if (*BufferOffset < ' ' || *BufferOffset > '~')
+ TextLine[Line] = '.';
+ else
+ TextLine[Line] = *BufferOffset;
+
+ BufferOffset++;
+ }
+
+ TextLine[Line] = '\0';
+ AsciiPrint ("|%a|\n", TextLine);
+ }
+
+ gBS->FreePool(Buffer);
+
+ return EFI_SUCCESS;
+ }
+ else if (AsciiStrCmp(Argv[1], "w") == 0)
+ {
+ Offset = AsciiStrHexToUintn(Argv[2]);
+ Length = AsciiStrHexToUintn(Argv[3]);
+ Buffer = (UINT8 *)AsciiStrHexToUintn(Argv[4]);
+
+#if USE_DISKIO
+ Status = gBS->LocateProtocol(&gEfiDiskIoProtocolGuid, NULL, (VOID **)&DiskIo);
+ if (EFI_ERROR(Status))
+ {
+ AsciiPrint("Did not locate DiskIO\n");
+ return Status;
+ }
+
+ Status = DiskIo->WriteDisk(DiskIo, SIGNATURE_32('f','l','s','h'), Offset, Length, Buffer);
+ if (EFI_ERROR(Status))
+ {
+ AsciiPrint("DiskIO write failed\n");
+ return Status;
+ }
+
+#else
+#endif
+
+ return EFI_SUCCESS;
+ }
+ else
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdTemplate[] =
+{
+ {
+ "reset",
+ " [type]; Reset system. type = [warm] [shutdown] default is cold reset",
+ NULL,
+ EblResetCmd
+ },
+ {
+ "exit",
+ "; Exit EBL",
+ NULL,
+ EblExitCmd
+ },
+ {
+ "help",
+ " [cmd]; Help on cmd or a list of all commands if cmd is ommited",
+ NULL,
+ EblHelpCmd
+ },
+ {
+ "break",
+ "; Generate debugging breakpoint",
+ NULL,
+ EblBreakPointCmd
+ },
+ {
+ "page",
+ " [on|off]]; toggle promting on command output larger than screen",
+ NULL,
+ EblPageCmd
+ },
+ {
+ "pause",
+ " [sec]; Pause for sec[10] seconds. ",
+ NULL,
+ EblPauseCmd
+ },
+ {
+ "sleep",
+ " [sec]; Sleep for sec[10] seconds. ",
+ NULL,
+ EblSleepCmd
+ },
+ {
+ "hexdump",
+ " filename ; dump a file as hex bytes",
+ NULL,
+ EblHexdumpCmd
+ },
+ {
+ "diskio",
+ " [r|w] offset [length [dataptr]]; do a DiskIO read or write ",
+ NULL,
+ EblDiskIoCmd
+ }
+};
+
+
+EFI_HANDLE gExternalCmdHandle = NULL;
+
+/**
+ Initialize the commands in this in this file
+**/
+VOID
+EblInitializeCmdTable (
+ VOID
+ )
+{
+
+ EblAddCommands (mCmdTemplate, sizeof (mCmdTemplate)/sizeof (EBL_COMMAND_TABLE));
+
+ gBS->InstallProtocolInterface (
+ &gExternalCmdHandle,
+ &gEfiEblAddCommandProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gEblAddCommand
+ );
+
+}
+
+
+VOID
+EblShutdownExternalCmdTable (
+ VOID
+ )
+{
+ gBS->UninstallProtocolInterface (gExternalCmdHandle, &gEfiEblAddCommandProtocolGuid, &gEblAddCommand);
+}
+
+
diff --git a/EmbeddedPkg/Ebl/Dir.c b/EmbeddedPkg/Ebl/Dir.c new file mode 100644 index 0000000000..4e9f7b98b2 --- /dev/null +++ b/EmbeddedPkg/Ebl/Dir.c @@ -0,0 +1,305 @@ +/** @file
+ Dir for EBL (Embedded Boot Loader)
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: CmdTemplate.c
+
+ Search/Replace Dir with the name of your new command
+
+**/
+
+#include "Ebl.h"
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *gFvFileType[] = {
+ "All",
+ "Raw",
+ "Freeform",
+ "SEC",
+ "PeiCore",
+ "DxeCore",
+ "PEIM",
+ "Driver",
+ "Combo Driver",
+ "Application",
+ "NULL",
+ "FV"
+};
+
+
+/**
+ Perform a dir on a device. The device must support Simple File System Protocol
+ or the FV protocol.
+
+ Argv[0] - "dir"
+ Argv[1] - Device Name:path. Path is optional
+ Argv[2] - Optional filename to match on. A leading * means match substring
+ Argv[3] - Optional FV file type
+
+ dir fs1:\efi ; perform a dir on fs1: device in the efi directory
+ dir fs1:\efi *.efi; perform a dir on fs1: device in the efi directory but
+ only print out files that contain the string *.efi
+ dir fv1:\ ; perform a dir on fv1: device in the efi directory
+ NOTE: fv devices do not contian subdirs
+ dir fv1:\ * PEIM ; will match all files of type SEC
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblDirCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ EFI_OPEN_FILE *File;
+ EFI_FILE_INFO *DirInfo;
+ UINTN ReadSize;
+ UINTN CurrentRow;
+ CHAR16 *MatchSubString;
+ EFI_STATUS GetNextFileStatus;
+ UINTN Key;
+ EFI_FV_FILETYPE SearchType;
+ EFI_FV_FILETYPE Type;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ EFI_GUID NameGuid;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ UINT32 AuthenticationStatus;
+ VOID *Section;
+ UINTN SectionSize;
+ EFI_FV_FILETYPE Index;
+ UINTN Length;
+ UINTN BestMatchCount;
+ CHAR16 UnicodeFileName[MAX_CMD_LINE];
+
+
+ if (Argc <= 1) {
+ // CWD not currently supported
+ return EFI_SUCCESS;
+ }
+
+ File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
+ if (File == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if (File->Type == EfiOpenFirmwareVolume) {
+ // FV Dir
+
+ SearchType = EFI_FV_FILETYPE_ALL;
+ UnicodeFileName[0] = '\0';
+ MatchSubString = &UnicodeFileName[0];
+ if (Argc > 2) {
+ AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);
+ if (UnicodeFileName[0] == '*') {
+ // Handle *Name substring matching
+ MatchSubString = &UnicodeFileName[1];
+ }
+
+ // Handle file type matchs
+ if (Argc > 3) {
+ // match a specific file type, always last argument
+ Length = AsciiStrLen (Argv[3]);
+ for (Index = 1, BestMatchCount = 0; Index < sizeof (gFvFileType)/sizeof (CHAR8 *); Index++) {
+ if (AsciiStriCmp (gFvFileType[Index], Argv[3]) == 0) {
+ // exact match
+ SearchType = Index;
+ break;
+ }
+
+ if (AsciiStrniCmp (Argv[3], gFvFileType[Index], Length) == 0) {
+ // partial match, so keep looking to make sure there is only one partial match
+ BestMatchCount++;
+ SearchType = Index;
+ }
+ }
+
+ if (BestMatchCount > 1) {
+ SearchType = EFI_FV_FILETYPE_ALL;
+ }
+ }
+ }
+
+ Fv = File->Fv;
+ Key = 0;
+ CurrentRow = 0;
+ do {
+ Type = SearchType;
+ GetNextFileStatus = Fv->GetNextFile (
+ Fv,
+ &Key,
+ &Type,
+ &NameGuid,
+ &Attributes,
+ &Size
+ );
+ if (!EFI_ERROR (GetNextFileStatus)) {
+ // Calculate size of entire file
+ Section = NULL;
+ Size = 0;
+ Status = Fv->ReadFile (
+ Fv,
+ &NameGuid,
+ Section,
+ &Size,
+ &Type,
+ &Attributes,
+ &AuthenticationStatus
+ );
+ if (!((Status == EFI_BUFFER_TOO_SMALL) || !EFI_ERROR (Status))) {
+ // EFI_SUCCESS or EFI_BUFFER_TOO_SMALL mean size is valid
+ Size = 0;
+ }
+
+ // read the UI seciton to do a name match.
+ Section = NULL;
+ Status = Fv->ReadSection (
+ Fv,
+ &NameGuid,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ &Section,
+ &SectionSize,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ if (StrStr (Section, MatchSubString) != NULL) {
+ AsciiPrint (" %g %s %a %,d\n", &NameGuid, Section, gFvFileType[Type], Size);
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
+ break;
+ }
+ }
+ FreePool (Section);
+ } else {
+ if (*MatchSubString == '\0') {
+ AsciiPrint (" %g %a %,d\n", &NameGuid, gFvFileType[Type], Size);
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
+ break;
+ }
+ }
+ }
+ }
+ } while (!EFI_ERROR (GetNextFileStatus));
+
+ } else if ((File->Type == EfiOpenFileSystem) || (File->Type == EfiOpenBlockIo)) {
+ // Simple File System DIR
+
+ if (File->FsFileInfo == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if (!(File->FsFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
+ return EFI_SUCCESS;
+ }
+
+ // Handle *Name substring matching
+ MatchSubString = NULL;
+ UnicodeFileName[0] = '\0';
+ if (Argc > 2) {
+ AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);
+ if (UnicodeFileName[0] == '*') {
+ MatchSubString = &UnicodeFileName[1];
+ }
+ }
+
+ File->FsFileHandle->SetPosition (File->FsFileHandle, 0);
+ for (CurrentRow = 0;;) {
+ // First read gets the size
+ DirInfo = NULL;
+ ReadSize = 0;
+ Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ // Allocate the buffer for the real read
+ DirInfo = AllocatePool (ReadSize);
+ if (DirInfo == NULL) {
+ goto Done;
+ }
+
+ // Read the data
+ Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
+ if ((EFI_ERROR (Status)) || (ReadSize == 0)) {
+ break;
+ }
+ } else {
+ break;
+ }
+
+ if (MatchSubString != NULL) {
+ if (StrStr (&DirInfo->FileName[0], MatchSubString) == NULL) {
+ // does not match *name argument, so skip
+ continue;
+ }
+ } else if (UnicodeFileName[0] != '\0') {
+ // is not an exact match for name argument, so skip
+ if (StrCmp (&DirInfo->FileName[0], UnicodeFileName) != 0) {
+ continue;
+ }
+ }
+
+ if (DirInfo->Attribute & EFI_FILE_DIRECTORY) {
+ AsciiPrint (" <DIR> %s\n", &DirInfo->FileName[0]);
+ } else {
+ AsciiPrint ("%,14ld %s\n", DirInfo->FileSize, &DirInfo->FileName[0]);
+ }
+
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
+ break;
+ }
+
+ FreePool (DirInfo);
+ }
+
+Done:
+ if (DirInfo != NULL) {
+ FreePool (DirInfo);
+ }
+ }
+
+ EfiClose (File);
+
+ return EFI_SUCCESS;
+}
+
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDirTemplate[] =
+{
+ {
+ "dir",
+ " dirdev [*match]; directory listing of dirdev. opt match a substring",
+ NULL,
+ EblDirCmd
+ }
+};
+
+
+/**
+ Initialize the commands in this in this file
+**/
+VOID
+EblInitializeDirCmd (
+ VOID
+ )
+{
+ if (FeaturePcdGet (PcdEmbeddedDirCmd)) {
+ EblAddCommands (mCmdDirTemplate, sizeof (mCmdDirTemplate)/sizeof (EBL_COMMAND_TABLE));
+ }
+}
+
diff --git a/EmbeddedPkg/Ebl/Ebl.h b/EmbeddedPkg/Ebl/Ebl.h new file mode 100644 index 0000000000..705511a0e4 --- /dev/null +++ b/EmbeddedPkg/Ebl/Ebl.h @@ -0,0 +1,194 @@ +/** @file + Include flie for basic command line parser for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation<BR> + Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EBL_H__ +#define __EBL_H__ + +#include <PiDxe.h> +#include <Protocol/BlockIo.h> +#include <Protocol/SimpleFileSystem.h> +#include <Protocol/FirmwareVolume2.h> +#include <Protocol/LoadFile.h> +#include <Protocol/FirmwareVolumeBlock.h> +#include <Protocol/PxeBaseCode.h> +#include <Protocol/LoadedImage.h> +#include <Protocol/EblAddCommand.h> +#include <Protocol/PciIo.h> +#include <Protocol/DevicePath.h> + +#include <Guid/FileInfo.h> +#include <Guid/DxeServices.h> +#include <Guid/MemoryTypeInformation.h> +#include <Guid/MemoryAllocationHob.h> +#include <Library/BaseLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DevicePathLib.h> +#include <Library/PrintLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/DebugLib.h> +#include <Library/EfiFileLib.h> +#include <Library/HobLib.h> +#include <Library/DebugLib.h> +#include <Library/IoLib.h> +#include <Library/PcdLib.h> +#include <Library/EblCmdLib.h> +#include <Library/DevicePathLib.h> +#include <Library/UefiLib.h> +#include <Library/EblNetworkLib.h> + +#include <IndustryStandard/Pci.h> + +// +// Prompt for the command line +// +#define CMD_SEPERATOR ';' +#define EBL_MAX_COMMAND_COUNT 0x100 +#define MAX_CMD_HISTORY 16 +#define MAX_CMD_LINE 256 +#define MAX_ARGS 32 + +#define EBL_CR 0x0a +#define EBL_LF 0x0d + +#define EFI_SET_TIMER_TO_SECOND 10000000 + + + +EBL_COMMAND_TABLE * +EblGetCommand ( + IN CHAR8 *CommandName + ); + + +EFI_STATUS +EblPathToDevice ( + IN CHAR8 *Path, + OUT EFI_HANDLE *DeviceHandle, + OUT EFI_DEVICE_PATH_PROTOCOL **PathDevicePath, + OUT VOID **Buffer, + OUT UINTN *BufferSize + ); + +BOOLEAN +EblAnyKeyToContinueQtoQuit ( + IN UINTN *CurrentRow, + IN BOOLEAN PrefixNewline + ); + +VOID +EblUpdateDeviceLists ( + VOID + ); + +VOID +EblInitializeCmdTable ( + VOID + ); + +VOID +EblShutdownExternalCmdTable ( + VOID + ); + +VOID +EblSetTextColor ( + UINTN Attribute + ); + + +EFI_STATUS +EblGetCharKey ( + IN OUT EFI_INPUT_KEY *Key, + IN UINTN TimoutInSec, + IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL + ); + +// BugBug: Move me to a library +INTN +EFIAPI +AsciiStrniCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ); + + +VOID +EblInitializeDeviceCmd ( + VOID + ); + +VOID +EblInitializemdHwDebugCmds ( + VOID + ); + +VOID +EblInitializeDirCmd ( + VOID + ); + +VOID +EblInitializeHobCmd ( + VOID + ); + +VOID +EblInitializemdHwIoDebugCmds ( + VOID + ); + +VOID +EblInitializeScriptCmd ( + VOID + ); + +VOID +EblInitializeNetworkCmd ( + VOID + ); + +CHAR8 * +ParseArguments ( + IN CHAR8 *CmdLine, + OUT UINTN *Argc, + OUT CHAR8 **Argv + ); + +EFI_STATUS +ProcessCmdLine ( + IN CHAR8 *CmdLine, + IN UINTN MaxCmdLineSize + ); + +EFI_STATUS +OutputData ( + IN UINT8 *Address, + IN UINTN Length, + IN UINTN Width, + IN UINTN Offset + ); + +extern UINTN gScreenColumns; +extern UINTN gScreenRows; +extern BOOLEAN gPageBreak; +extern CHAR8 *gMemMapType[]; + +#endif + diff --git a/EmbeddedPkg/Ebl/Ebl.inf b/EmbeddedPkg/Ebl/Ebl.inf new file mode 100644 index 0000000000..f3413546be --- /dev/null +++ b/EmbeddedPkg/Ebl/Ebl.inf @@ -0,0 +1,110 @@ +#%HEADER%
+#/** @file
+# EBL Applicaiton
+#
+# This is a shell application that will display Hello World.
+# Copyright (c) 2007, Intel Corporation.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Ebl
+ FILE_GUID = 3CEF354A-3B7A-4519-AD70-72A134698311
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = EdkBootLoaderEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+[Sources.common]
+ Main.c
+ Command.c
+ EfiDevice.c
+ HwDebug.c
+ HwIoDebug.c
+ Dir.c
+ Hob.c
+ Script.c
+ Ebl.h
+ Network.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ UefiLib
+ UefiApplicationEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ DevicePathLib
+ IoLib
+ PrintLib
+ PcdLib
+ EfiFileLib
+ HobLib
+ BaseLib
+ EblCmdLib
+ EblNetworkLib
+
+[LibraryClasses.ARM]
+ SemihostLib
+
+[Protocols.common]
+ gEfiFirmwareVolume2ProtocolGuid
+ gEfiFirmwareVolumeBlockProtocolGuid
+ gEfiBlockIoProtocolGuid
+ gEfiSimpleFileSystemProtocolGuid
+ gEfiLoadFileProtocolGuid
+ gEfiLoadedImageProtocolGuid
+ gEfiPxeBaseCodeProtocolGuid
+ gEfiEblAddCommandProtocolGuid
+ gEfiDiskIoProtocolGuid
+ gEfiPciIoProtocolGuid
+ gEfiSimpleNetworkProtocolGuid
+
+[Guids.common]
+ gEfiDxeServicesTableGuid
+ gEfiFileInfoGuid
+ gEfiHobMemoryAllocModuleGuid
+ gEfiMemoryTypeInformationGuid
+
+[FeaturePcd.common]
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd
+
+[FixedPcd.common]
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedShellCharacterEcho
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt
+
diff --git a/EmbeddedPkg/Ebl/EfiDevice.c b/EmbeddedPkg/Ebl/EfiDevice.c new file mode 100644 index 0000000000..7633d66934 --- /dev/null +++ b/EmbeddedPkg/Ebl/EfiDevice.c @@ -0,0 +1,969 @@ +/** @file
+ EBL commands for EFI and PI Devices
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Ebl.h"
+
+
+EFI_DXE_SERVICES *gDS = NULL;
+
+
+/**
+ Print information about the File System device.
+
+ @param File Open File for the device
+
+**/
+VOID
+EblPrintFsInfo (
+ IN EFI_OPEN_FILE *File
+ )
+{
+ if (File == NULL) {
+ return;
+ }
+
+ AsciiPrint (" %a: ", File->DeviceName);
+ if (File->FsInfo != NULL) {
+ AsciiPrint ("%s: ", File->FsInfo->VolumeLabel);
+ if (File->FsInfo->ReadOnly) {
+ AsciiPrint ("ReadOnly");
+ }
+ }
+
+ AsciiPrint ("\n");
+ EfiClose (File);
+}
+
+
+/**
+ Print information about the FV devices.
+
+ @param File Open File for the device
+
+**/
+VOID
+EblPrintFvbInfo (
+ IN EFI_OPEN_FILE *File
+ )
+{
+ if (File == NULL) {
+ return;
+ }
+
+ AsciiPrint (" %a: 0x%08lx - 0x%08lx : 0x%08x\n", File->DeviceName, File->FvStart, File->FvStart + File->FvSize - 1, File->FvSize);
+ EfiClose (File);
+}
+
+
+/**
+ Print information about the Blk IO devices.
+ If the device supports PXE dump out extra information
+
+ @param File Open File for the device
+
+**/
+VOID
+EblPrintBlkIoInfo (
+ IN EFI_OPEN_FILE *File
+ )
+{
+ UINT64 DeviceSize;
+
+
+ if (File == NULL) {
+ return;
+ }
+
+ AsciiPrint (" %a: ", File->DeviceName);
+ if (File->FsBlockIoMedia.RemovableMedia) {
+ AsciiPrint ("Removable ");
+ }
+ if (!File->FsBlockIoMedia.MediaPresent) {
+ AsciiPrint ("No Media ");
+ }
+ if (File->FsBlockIoMedia.LogicalPartition) {
+ AsciiPrint ("Partition ");
+ }
+ DeviceSize = MultU64x32 (File->FsBlockIoMedia.LastBlock + 1, File->FsBlockIoMedia.BlockSize);
+ AsciiPrint ("Size = 0x%lX\n", DeviceSize);
+
+ EfiClose (File);
+}
+
+
+ /**
+ Print information about the Load File devices.
+ If the device supports PXE dump out extra information
+
+ @param File Open File for the device
+
+**/
+VOID
+EblPrintLoadFileInfo (
+ IN EFI_OPEN_FILE *File
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
+ MAC_ADDR_DEVICE_PATH *MacAddr;
+ UINTN HwAddressSize;
+ UINTN Index;
+
+ if (File == NULL) {
+ return;
+ }
+
+ AsciiPrint (" %a: %a ", File->DeviceName, EblLoadFileBootTypeString (File->EfiHandle));
+
+ if (File->DevicePath != NULL) {
+ // Try to print out the MAC address
+ for (DevicePathNode = File->DevicePath;
+ !IsDevicePathEnd (DevicePathNode);
+ DevicePathNode = NextDevicePathNode (DevicePathNode)) {
+
+ if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePathNode) == MSG_MAC_ADDR_DP)) {
+ MacAddr = (MAC_ADDR_DEVICE_PATH *)DevicePathNode;
+
+ HwAddressSize = sizeof (EFI_MAC_ADDRESS);
+ if (MacAddr->IfType == 0x01 || MacAddr->IfType == 0x00) {
+ HwAddressSize = 6;
+ }
+
+ AsciiPrint ("MAC ");
+ for (Index = 0; Index < HwAddressSize; Index++) {
+ AsciiPrint ("%02x", MacAddr->MacAddress.Addr[Index] & 0xff);
+ }
+ }
+ }
+ }
+
+ AsciiPrint ("\n");
+ EfiClose (File);
+ return;
+}
+
+
+
+/**
+ Dump information about devices in the system.
+
+ fv: PI Firmware Volume
+ fs: EFI Simple File System
+ blk: EFI Block IO
+ LoadFile: EFI Load File Protocol (commonly PXE network boot)
+
+ Argv[0] - "device"
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblDeviceCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINTN Index;
+ UINTN CurrentRow;
+ UINTN Max;
+
+ CurrentRow = 0;
+
+ // Need to call here to make sure Device Counts are valid
+ EblUpdateDeviceLists ();
+
+ Max = EfiGetDeviceCounts (EfiOpenFirmwareVolume);
+ if (Max != 0) {
+ AsciiPrint ("Firmware Volume Devices:\n");
+ for (Index = 0; Index < Max; Index++) {
+ EblPrintFvbInfo (EfiDeviceOpenByType (EfiOpenFirmwareVolume, Index));
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
+ break;
+ }
+ }
+ }
+
+ Max = EfiGetDeviceCounts (EfiOpenFileSystem);
+ if (Max != 0) {
+ AsciiPrint ("File System Devices:\n");
+ for (Index = 0; Index < Max; Index++) {
+ EblPrintFsInfo (EfiDeviceOpenByType (EfiOpenFileSystem, Index));
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
+ break;
+ }
+ }
+ }
+
+ Max = EfiGetDeviceCounts (EfiOpenBlockIo);
+ if (Max != 0) {
+ AsciiPrint ("Block IO Devices:\n");
+ for (Index = 0; Index < Max; Index++) {
+ EblPrintBlkIoInfo (EfiDeviceOpenByType (EfiOpenBlockIo, Index));
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
+ break;
+ }
+ }
+ }
+
+ Max = EfiGetDeviceCounts (EfiOpenLoadFile);
+ if (Max != 0) {
+ AsciiPrint ("LoadFile Devices: (usually network)\n");
+ for (Index = 0; Index < Max; Index++) {
+ EblPrintLoadFileInfo (EfiDeviceOpenByType (EfiOpenLoadFile, Index));
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
+ break;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Start an EFI image (PE32+ with EFI defined entry point).
+
+ Argv[0] - "start"
+ Argv[1] - device name and path
+ Argv[2] - "" string to pass into image being started
+
+ start fs1:\Temp\Fv.Fv "arg to pass" ; load an FV from the disk and pass the
+ ; ascii string arg to pass to the image
+ start fv0:\FV ; load an FV from an FV (not common)
+ start LoadFile0: ; load an FV via a PXE boot
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblStartCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ EFI_OPEN_FILE *File;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HANDLE ImageHandle;
+ UINTN ExitDataSize;
+ CHAR16 *ExitData;
+ VOID *Buffer;
+ UINTN BufferSize;
+ EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
+
+ ImageHandle = NULL;
+
+ if (Argc < 2) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DevicePath = File->DevicePath;
+ if (DevicePath != NULL) {
+ // check for device path form: blk, fv, fs, and loadfile
+ Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, NULL, 0, &ImageHandle);
+ } else {
+ // Check for buffer form: A0x12345678:0x1234 syntax.
+ // Means load using buffer starting at 0x12345678 of size 0x1234.
+
+ Status = EfiReadAllocatePool (File, &Buffer, &BufferSize);
+ if (EFI_ERROR (Status)) {
+ EfiClose (File);
+ return Status;
+ }
+ Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, Buffer, BufferSize, &ImageHandle);
+
+ FreePool (Buffer);
+ }
+
+ EfiClose (File);
+
+ if (!EFI_ERROR (Status)) {
+ if (Argc >= 3) {
+ // Argv[2] is a "" string that we pass directly to the EFI application without the ""
+ // We don't pass Argv[0] to the EFI Application (it's name) just the args
+ Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);
+ ASSERT_EFI_ERROR (Status);
+
+ ImageInfo->LoadOptionsSize = (UINT32)AsciiStrSize (Argv[2]);
+ ImageInfo->LoadOptions = AllocatePool (ImageInfo->LoadOptionsSize);
+ AsciiStrCpy (ImageInfo->LoadOptions, Argv[2]);
+ }
+
+ // Transfer control to the EFI image we loaded with LoadImage()
+ Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);
+ }
+
+ return Status;
+}
+
+
+/**
+ Load a Firmware Volume (FV) into memory from a device. This causes drivers in
+ the FV to be dispatched if the dependancies of the drivers are met.
+
+ Argv[0] - "loadfv"
+ Argv[1] - device name and path
+
+ loadfv fs1:\Temp\Fv.Fv ; load an FV from the disk
+ loadfv fv0:\FV ; load an FV from an FV (not common)
+ loadfv LoadFile0: ; load an FV via a PXE boot
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblLoadFvCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ EFI_OPEN_FILE *File;
+ VOID *FvStart;
+ UINTN FvSize;
+ EFI_HANDLE FvHandle;
+
+
+ if (Argc < 2) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (File->Type == EfiOpenMemoryBuffer) {
+ // If it is a address just use it.
+ Status = gDS->ProcessFirmwareVolume (File->Buffer, File->Size, &FvHandle);
+ } else {
+ // If it is a file read it into memory and use it
+ Status = EfiReadAllocatePool (File, &FvStart, &FvSize);
+ EfiClose (File);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gDS->ProcessFirmwareVolume (FvStart, FvSize, &FvHandle);
+ FreePool (FvStart);
+ }
+ return Status;
+}
+
+
+/**
+ Perform an EFI connect to connect devices that follow the EFI driver model.
+ If it is a PI system also call the dispatcher in case a new FV was made
+ availible by one of the connect EFI drivers (this is not a common case).
+
+ Argv[0] - "connect"
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblConnectCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ BOOLEAN Dispatch;
+ EFI_OPEN_FILE *File;
+
+
+ if (Argc > 1) {
+ if ((*Argv[1] == 'd') || (*Argv[1] == 'D')) {
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
+ }
+
+ //
+ // Given we disconnect our console we should go and do a connect now
+ //
+ } else {
+ File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
+ if (File != NULL) {
+ AsciiPrint ("Connecting %a\n", Argv[1]);
+ gBS->ConnectController (File->EfiHandle, NULL, NULL, TRUE);
+ EfiClose (File);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ Dispatch = FALSE;
+ do {
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+
+ FreePool (HandleBuffer);
+
+ //
+ // Check to see if it's possible to dispatch an more DXE drivers.
+ // The BdsLibConnectAllEfi () may have made new DXE drivers show up.
+ // If anything is Dispatched Status == EFI_SUCCESS and we will try
+ // the connect again.
+ //
+ if (gDS == NULL) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ Status = gDS->Dispatch ();
+ if (!EFI_ERROR (Status)) {
+ Dispatch = TRUE;
+ }
+ }
+
+ } while (!EFI_ERROR (Status));
+
+ if (Dispatch) {
+ AsciiPrint ("Connected and dispatched\n");
+ } else {
+ AsciiPrint ("Connect\n");
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+CHAR8 *gMemMapType[] = {
+ "reserved ",
+ "LoaderCode",
+ "LoaderData",
+ "BS_code ",
+ "BS_data ",
+ "RT_code ",
+ "RT_data ",
+ "available ",
+ "Unusable ",
+ "ACPI_recl ",
+ "ACPI_NVS ",
+ "MemMapIO ",
+ "MemPortIO ",
+ "PAL_code "
+};
+
+
+/**
+ Dump out the EFI memory map
+
+ Argv[0] - "memmap"
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblMemMapCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ EFI_MEMORY_DESCRIPTOR *MemMap;
+ EFI_MEMORY_DESCRIPTOR *OrigMemMap;
+ UINTN MemMapSize;
+ UINTN MapKey;
+ UINTN DescriptorSize;
+ UINT32 DescriptorVersion;
+ UINT64 PageCount[EfiMaxMemoryType];
+ UINTN Index;
+ UINT64 EntrySize;
+ UINTN CurrentRow;
+ UINT64 TotalMemory;
+
+ ZeroMem (PageCount, sizeof (PageCount));
+
+ AsciiPrint ("EFI Memory Map\n");
+
+ // First call is to figure out how big the buffer needs to be
+ MemMapSize = 0;
+ MemMap = NULL;
+ Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ // In case the AllocatPool changes the memory map we added in some extra descriptors
+ MemMapSize += (DescriptorSize * 0x100);
+ OrigMemMap = MemMap = AllocatePool (MemMapSize);
+ if (OrigMemMap != NULL) {
+ // 2nd time we get the data
+ Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0, CurrentRow = 0; Index < MemMapSize/DescriptorSize; Index++) {
+ EntrySize = LShiftU64 (MemMap->NumberOfPages, 12);
+ AsciiPrint ("\n%a %016lx - %016lx: # %08lx %016lx", gMemMapType[MemMap->Type % EfiMaxMemoryType], MemMap->PhysicalStart, MemMap->PhysicalStart + EntrySize -1, MemMap->NumberOfPages, MemMap->Attribute);
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
+ break;
+ }
+
+ PageCount[MemMap->Type % EfiMaxMemoryType] += MemMap->NumberOfPages;
+ MemMap = NEXT_MEMORY_DESCRIPTOR (MemMap, DescriptorSize);
+ }
+ }
+
+ for (Index = 0, TotalMemory = 0; Index < EfiMaxMemoryType; Index++) {
+ if (PageCount[Index] != 0) {
+ AsciiPrint ("\n %a %,7ld Pages (%,14ld)", gMemMapType[Index], PageCount[Index], LShiftU64 (PageCount[Index], 12));
+ if (Index == EfiLoaderCode ||
+ Index == EfiLoaderData ||
+ Index == EfiBootServicesCode ||
+ Index == EfiBootServicesData ||
+ Index == EfiRuntimeServicesCode ||
+ Index == EfiRuntimeServicesData ||
+ Index == EfiConventionalMemory ||
+ Index == EfiACPIReclaimMemory ||
+ Index == EfiACPIMemoryNVS ||
+ Index == EfiPalCode
+ ) {
+ // Count total memory
+ TotalMemory += PageCount[Index];
+ }
+ }
+ }
+
+ AsciiPrint ("\nTotal Memory: %,ld MB (%,ld bytes)\n", RShiftU64 (TotalMemory, 8), LShiftU64 (TotalMemory, 12));
+
+ FreePool (OrigMemMap);
+
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+/**
+ Load a file into memory and optionally jump to it. A load addres can be
+ specified or automatically allocated. A quoted command line can optionally
+ be passed into the image.
+
+ Argv[0] - "go"
+ Argv[1] - Device Name:path for the file to load
+ Argv[2] - Address to load to or '*' if the load address will be allocated
+ Argv[3] - Optional Entry point to the image. Image will be called if present
+ Argv[4] - "" string that will be passed as Argc & Argv to EntryPoint. Needs
+ to include the command name
+
+ go fv1:\EblCmdX 0x10000 0x10010 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX
+ from FV1 to location 0x10000 and call the entry point at 0x10010 passing
+ in "EblCmdX Arg2 Arg3 Arg4" as the arguments.
+
+ go fv0:\EblCmdX * 0x10 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX from FS0
+ to location allocated by this comamnd and call the entry point at offset 0x10
+ passing in "EblCmdX Arg2 Arg3 Arg4" as the arguments.
+
+ go fv1:\EblCmdX 0x10000; Load EblCmdX to address 0x10000 and return
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblGoCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ EFI_OPEN_FILE *File;
+ VOID *Address;
+ UINTN Size;
+ EBL_COMMMAND EntryPoint;
+ UINTN EntryPointArgc;
+ CHAR8 *EntryPointArgv[MAX_ARGS];
+
+
+ if (Argc <= 2) {
+ // device name and laod address are required
+ return EFI_SUCCESS;
+ }
+
+ File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
+ if (File == NULL) {
+ AsciiPrint (" %a is not a valid path\n", Argv[1]);
+ return EFI_SUCCESS;
+ }
+
+ EntryPoint = (EBL_COMMMAND)((Argc > 3) ? (UINTN)AsciiStrHexToUintn (Argv[3]) : (UINTN)NULL);
+ if (Argv[2][0] == '*') {
+ // * Means allocate the buffer
+ Status = EfiReadAllocatePool (File, &Address, &Size);
+
+ // EntryPoint is relatvie to the start of the image
+ EntryPoint = (EBL_COMMMAND)((UINTN)EntryPoint + (UINTN)Address);
+
+ } else {
+ Address = (VOID *)AsciiStrHexToUintn (Argv[2]);
+ Size = File->Size;
+
+ // File->Size for LoadFile is lazy so we need to use the tell to figure it out
+ EfiTell (File, NULL);
+ Status = EfiRead (File, Address, &Size);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ AsciiPrint ("Loaded %,d bytes to 0x%08x\n", Size, Address);
+
+ if (Argc > 3) {
+ if (Argc > 4) {
+ ParseArguments (Argv[4], &EntryPointArgc, EntryPointArgv);
+ } else {
+ EntryPointArgc = 1;
+ EntryPointArgv[0] = File->FileName;
+ }
+
+ Status = EntryPoint (EntryPointArgc, EntryPointArgv);
+ }
+ }
+
+ EfiClose (File);
+ return Status;
+}
+
+#define FILE_COPY_CHUNK 0x20000
+
+EFI_STATUS
+EblFileCopyCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_OPEN_FILE *Source = NULL;
+ EFI_OPEN_FILE *Destination = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+ VOID *Buffer = NULL;
+ UINTN Size;
+ UINTN Offset;
+ UINTN Chunk = FILE_COPY_CHUNK;
+
+ if (Argc < 3) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Source = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);
+ if (Source == NULL) {
+ AsciiPrint("Source file open error.\n");
+ return EFI_NOT_FOUND;
+ }
+
+ Destination = EfiOpen(Argv[2], EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
+ if (Destination == NULL) {
+ AsciiPrint("Destination file open error.\n");
+ return EFI_NOT_FOUND;
+ }
+
+ Buffer = AllocatePool(FILE_COPY_CHUNK);
+ if (Buffer == NULL) {
+ goto Exit;
+ }
+
+ Size = EfiTell(Source, NULL);
+
+ for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size; Offset += Chunk) {
+ Chunk = FILE_COPY_CHUNK;
+
+ Status = EfiRead(Source, Buffer, &Chunk);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("Read file error\n");
+ goto Exit;
+ }
+
+ Status = EfiWrite(Destination, Buffer, &Chunk);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("Write file error\n");
+ goto Exit;
+ }
+ }
+
+ // Any left over?
+ if (Offset < Size) {
+ Chunk = Size - Offset;
+
+ Status = EfiRead(Source, Buffer, &Chunk);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("Read file error\n");
+ goto Exit;
+ }
+
+ Status = EfiWrite(Destination, Buffer, &Chunk);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("Write file error\n");
+ goto Exit;
+ }
+ }
+
+Exit:
+ if (Source != NULL) {
+ Status = EfiClose(Source);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("Source close error %r\n", Status);
+ }
+ }
+
+ if (Destination != NULL) {
+ Status = EfiClose(Destination);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("Destination close error %r\n", Status);
+ }
+ }
+
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EblFileDiffCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_OPEN_FILE *File1 = NULL;
+ EFI_OPEN_FILE *File2 = NULL;
+ EFI_STATUS Status = EFI_SUCCESS;
+ VOID *Buffer1 = NULL;
+ VOID *Buffer2 = NULL;
+ UINTN Size1;
+ UINTN Size2;
+ UINTN Offset;
+ UINTN Chunk = FILE_COPY_CHUNK;
+
+ if (Argc != 3) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ File1 = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);
+ if (File1 == NULL) {
+ AsciiPrint("File 1 open error.\n");
+ return EFI_NOT_FOUND;
+ }
+
+ File2 = EfiOpen(Argv[2], EFI_FILE_MODE_READ, 0);
+ if (File2 == NULL) {
+ AsciiPrint("File 2 open error.\n");
+ return EFI_NOT_FOUND;
+ }
+
+ Size1 = EfiTell(File1, NULL);
+ Size2 = EfiTell(File2, NULL);
+
+ if (Size1 != Size2) {
+ AsciiPrint("Files differ.\n");
+ goto Exit;
+ }
+
+ Buffer1 = AllocatePool(FILE_COPY_CHUNK);
+ if (Buffer1 == NULL) {
+ goto Exit;
+ }
+
+ Buffer2 = AllocatePool(FILE_COPY_CHUNK);
+ if (Buffer2 == NULL) {
+ goto Exit;
+ }
+
+ for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size1; Offset += Chunk) {
+ Chunk = FILE_COPY_CHUNK;
+
+ Status = EfiRead(File1, Buffer1, &Chunk);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("File 1 read error\n");
+ goto Exit;
+ }
+
+ Status = EfiRead(File2, Buffer2, &Chunk);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("File 2 read error\n");
+ goto Exit;
+ }
+
+ if (CompareMem(Buffer1, Buffer2, Chunk) != 0) {
+ AsciiPrint("Files differ.\n");
+ goto Exit;
+ };
+ }
+
+ // Any left over?
+ if (Offset < Size1) {
+ Chunk = Size1 - Offset;
+
+ Status = EfiRead(File1, Buffer1, &Chunk);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("File 1 read error\n");
+ goto Exit;
+ }
+
+ Status = EfiRead(File2, Buffer2, &Chunk);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("File 2 read error\n");
+ goto Exit;
+ }
+ }
+
+ if (CompareMem(Buffer1, Buffer2, Chunk) != 0) {
+ AsciiPrint("Files differ.\n");
+ } else {
+ AsciiPrint("Files are identical.\n");
+ }
+
+Exit:
+ if (File1 != NULL) {
+ Status = EfiClose(File1);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("File 1 close error %r\n", Status);
+ }
+ }
+
+ if (File2 != NULL) {
+ Status = EfiClose(File2);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("File 2 close error %r\n", Status);
+ }
+ }
+
+ if (Buffer1 != NULL) {
+ FreePool(Buffer1);
+ }
+
+ if (Buffer2 != NULL) {
+ FreePool(Buffer2);
+ }
+
+ return Status;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDeviceTemplate[] =
+{
+ {
+ "connect",
+ "[d]; Connect all EFI devices. d means disconnect",
+ NULL,
+ EblConnectCmd
+ },
+ {
+ "device",
+ "; Show information about boot devices",
+ NULL,
+ EblDeviceCmd
+ },
+ {
+ "go",
+ " dev:path loadaddress entrypoint args; load to given address and jump in",
+ NULL,
+ EblGoCmd
+ },
+ {
+ "loadfv",
+ " devname; Load PI FV from device",
+ NULL,
+ EblLoadFvCmd
+ },
+ {
+ "start",
+ " path; EFI Boot Device:filepath. fs1:\\EFI\\BOOT.EFI",
+ NULL,
+ EblStartCmd
+ },
+ {
+ "memmap",
+ "; dump EFI memory map",
+ NULL,
+ EblMemMapCmd
+ },
+ {
+ "cp",
+ " file1 file2; copy file",
+ NULL,
+ EblFileCopyCmd
+ },
+ {
+ "diff",
+ " file1 file2; compare files",
+ NULL,
+ EblFileDiffCmd
+ }
+};
+
+
+/**
+ Initialize the commands in this in this file
+**/
+
+VOID
+EblInitializeDeviceCmd (
+ VOID
+ )
+{
+ EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS);
+ EblAddCommands (mCmdDeviceTemplate, sizeof (mCmdDeviceTemplate)/sizeof (EBL_COMMAND_TABLE));
+}
+
diff --git a/EmbeddedPkg/Ebl/Hob.c b/EmbeddedPkg/Ebl/Hob.c new file mode 100644 index 0000000000..c541f66968 --- /dev/null +++ b/EmbeddedPkg/Ebl/Hob.c @@ -0,0 +1,232 @@ +/** @file
+ Hob command for EBL (Embedded Boot Loader)
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: Hob.c
+
+ Search/Replace Dir with the name of your new command
+
+ Boot Mode:
+ ==========
+ BOOT_WITH_FULL_CONFIGURATION 0x00
+ BOOT_WITH_MINIMAL_CONFIGURATION 0x01
+ BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02
+ BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS 0x03
+ BOOT_WITH_DEFAULT_SETTINGS 0x04
+ BOOT_ON_S4_RESUME 0x05
+ BOOT_ON_S5_RESUME 0x06
+ BOOT_ON_S2_RESUME 0x10
+ BOOT_ON_S3_RESUME 0x11
+ BOOT_ON_FLASH_UPDATE 0x12
+ BOOT_IN_RECOVERY_MODE 0x20
+ BOOT_IN_RECOVERY_MODE_MASK 0x40
+ BOOT_SPECIAL_MASK 0x80
+
+ Mem Alloc HOB Type:
+ ===================
+ typedef enum {
+ EfiReservedMemoryType = 0x00
+ EfiLoaderCode = 0x01
+ EfiLoaderData = 0x02
+ EfiBootServicesCode = 0x03
+ EfiBootServicesData = 0x04
+ EfiRuntimeServicesCode = 0x05
+ EfiRuntimeServicesData = 0x06
+ EfiConventionalMemory = 0x07
+ EfiUnusableMemory = 0x08
+ EfiACPIReclaimMemory = 0x09
+ EfiACPIMemoryNVS = 0x0a
+ EfiMemoryMappedIO = 0x0b
+ EfiMemoryMappedIOPortSpace = 0x0c
+ EfiPalCode = 0x0d
+ EfiMaxMemoryType = 0x0e
+ } EFI_MEMORY_TYPE;
+
+ Resource Hob Tye:
+ =================
+ EFI_RESOURCE_SYSTEM_MEMORY 0
+ EFI_RESOURCE_MEMORY_MAPPED_IO 1
+ EFI_RESOURCE_IO 2
+ EFI_RESOURCE_FIRMWARE_DEVICE 3
+ EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 4
+ EFI_RESOURCE_MEMORY_RESERVED 5
+ EFI_RESOURCE_IO_RESERVED 6
+ EFI_RESOURCE_MAX_MEMORY_TYPE 7
+
+ Resource Hob Attribute (last thing printed):
+ ============================================
+ EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002
+ EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004
+ EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008
+ EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010
+ EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020
+ EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040
+ EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080
+ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100
+ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000
+ EFI_RESOURCE_ATTRIBUTE_16_BIT_IO 0x00004000
+ EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000
+ EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000
+ EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000
+
+**/
+
+#include "Ebl.h"
+// BugBug: Autogen does not allow this to be included currently
+//#include <EdkModulePkg/Include/EdkDxe.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED char *mHobResourceType[] = {
+ "Memory ",
+ "MMIO ",
+ "IO ",
+ "Firmware ",
+ "MMIO Port ",
+ "Reserved ",
+ "IO Reserved",
+ "Illegal "
+};
+
+
+/**
+ Dump out the HOBs in the system. HOBs are defined in the PI specificaiton
+ and they are used to hand off information from PEI to DXE.
+
+ Argv[0] - "hob"
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblHobCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINTN CurrentRow;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation;
+ UINTN Index;
+
+ CurrentRow = 0;
+ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
+ AsciiPrint ("PHIT HOB Ver %x Boot Mode %02x Top %lx Bottom %lx\n",
+ Hob.HandoffInformationTable->Version,
+ Hob.HandoffInformationTable->BootMode,
+ Hob.HandoffInformationTable->EfiMemoryTop,
+ Hob.HandoffInformationTable->EfiMemoryBottom
+ );
+
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
+ return EFI_SUCCESS;
+ }
+
+ AsciiPrint (" Free Top %lx Free Bottom %lx End Of HOB %lx\n",
+ Hob.HandoffInformationTable->EfiFreeMemoryTop,
+ Hob.HandoffInformationTable->EfiFreeMemoryBottom,
+ Hob.HandoffInformationTable->EfiEndOfHobList
+ );
+
+ } else if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
+ // mod(%) on array index is just to prevent buffer overrun
+ AsciiPrint ("Mem Alloc HOB %a %g %08lx:%lx\n",
+ (Hob.MemoryAllocation->AllocDescriptor.MemoryType < EfiMaxMemoryType) ? gMemMapType[Hob.MemoryAllocation->AllocDescriptor.MemoryType] : "ILLEGAL TYPE",
+ &Hob.MemoryAllocation->AllocDescriptor.Name,
+ Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress,
+ Hob.MemoryAllocation->AllocDescriptor.MemoryLength
+ );
+ if (CompareGuid (&gEfiHobMemoryAllocModuleGuid, &Hob.MemoryAllocation->AllocDescriptor.Name)) {
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
+ return EFI_SUCCESS;
+ }
+ AsciiPrint (" Module Name %g EntryPoint %lx\n", &Hob.MemoryAllocationModule->ModuleName, Hob.MemoryAllocationModule->EntryPoint);
+ }
+ } else if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ AsciiPrint ("Resource HOB %a %g %08lx:%lx\n Attributes: %08x\n",
+ (Hob.ResourceDescriptor->ResourceType < EFI_RESOURCE_MAX_MEMORY_TYPE) ? mHobResourceType[Hob.ResourceDescriptor->ResourceType] : mHobResourceType[EFI_RESOURCE_MAX_MEMORY_TYPE],
+ &Hob.ResourceDescriptor->Owner,
+ Hob.ResourceDescriptor->PhysicalStart,
+ Hob.ResourceDescriptor->ResourceLength,
+ Hob.ResourceDescriptor->ResourceAttribute
+ );
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
+ return EFI_SUCCESS;
+ }
+ } else if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
+ AsciiPrint ("GUID HOB %g\n", &Hob.Guid->Name);
+ if (CompareGuid (&gEfiMemoryTypeInformationGuid, &Hob.Guid->Name)) {
+ EfiMemoryTypeInformation = GET_GUID_HOB_DATA (Hob.Guid);
+ for (Index = 0; Index < (GET_GUID_HOB_DATA_SIZE (Hob.Guid)/sizeof (EFI_MEMORY_TYPE_INFORMATION)); Index++, EfiMemoryTypeInformation++) {
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
+ return EFI_SUCCESS;
+ }
+ AsciiPrint (" %a 0x%08x\n",
+ (EfiMemoryTypeInformation->Type < EfiMaxMemoryType) ? gMemMapType[EfiMemoryTypeInformation->Type] : "END ",
+ EfiMemoryTypeInformation->NumberOfPages
+ );
+ }
+ }
+ } else if (Hob.Header->HobType == EFI_HOB_TYPE_FV) {
+ AsciiPrint ("FV HOB %08lx:%08lx\n", Hob.FirmwareVolume->BaseAddress, Hob.FirmwareVolume->Length);
+ } else if (Hob.Header->HobType == EFI_HOB_TYPE_CPU) {
+ AsciiPrint ("CPU HOB: Mem %x IO %x\n", Hob.Cpu->SizeOfMemorySpace, Hob.Cpu->SizeOfIoSpace);
+ } else if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_POOL) {
+ AsciiPrint ("Mem Pool HOB:\n");
+/* Not in PI
+ } else if (Hob.Header->HobType == EFI_HOB_TYPE_CV) {
+ AsciiPrint ("CV HOB: %08lx:%08lx\n", Hob.CapsuleVolume->BaseAddress, Hob.CapsuleVolume->Length);
+ */
+ }
+
+ if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
+ break;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHobTemplate[] =
+{
+ {
+ "hob",
+ "; dump HOBs",
+ NULL,
+ EblHobCmd
+ }
+};
+
+
+/**
+ Initialize the commands in this in this file
+**/
+VOID
+EblInitializeHobCmd (
+ VOID
+ )
+{
+ if (FeaturePcdGet (PcdEmbeddedHobCmd)) {
+ EblAddCommands (mCmdHobTemplate, sizeof (mCmdHobTemplate)/sizeof (EBL_COMMAND_TABLE));
+ }
+}
+
diff --git a/EmbeddedPkg/Ebl/HwDebug.c b/EmbeddedPkg/Ebl/HwDebug.c new file mode 100644 index 0000000000..6ffbaf1170 --- /dev/null +++ b/EmbeddedPkg/Ebl/HwDebug.c @@ -0,0 +1,342 @@ +/** @file
+ Basic command line parser for EBL (Embedded Boot Loader)
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: HwDebug.c
+
+ Commands useful for debugging hardware.
+
+**/
+
+#include "Ebl.h"
+
+
+/**
+ Dump memory
+
+ Argv[0] - "md"
+ Argv[1] - Hex Address to dump
+ Argv[2] - Number of hex bytes to dump (0x20 is default)
+ Argv[3] - [1|2|4|8] byte width of the dump
+
+ md 0x123445678 50 4 ; Dump 0x50 4 byte quantities starting at 0x123445678
+ md 0x123445678 40 ; Dump 0x40 1 byte quantities starting at 0x123445678
+ md 0x123445678 ; Dump 0x20 1 byte quantities starting at 0x123445678
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblMdCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ STATIC UINT8 *Address = NULL;
+ STATIC UINTN Length = 0x20;
+ STATIC UINTN Width = 1;
+
+ switch (Argc)
+ {
+ case 4:
+ Width = AsciiStrHexToUintn(Argv[3]);
+ case 3:
+ Length = AsciiStrHexToUintn(Argv[2]);
+ case 2:
+ Address = (UINT8 *)AsciiStrHexToUintn(Argv[1]);
+ default:
+ break;
+ }
+
+ OutputData(Address, Length, Width, (UINTN)Address);
+
+ Address += Length;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Fill Memory with data
+
+ Argv[0] - "mfill"
+ Argv[1] - Hex Address to fill
+ Argv[2] - Data to write (0x00 is default)
+ Argv[3] - Number of units to dump.
+ Argv[4] - [1|2|4|8] byte width of the dump
+
+ mf 0x123445678 aa 1 100 ; Start at 0x123445678 and write aa (1 byte) to the next 100 bytes
+ mf 0x123445678 aa 4 100 ; Start at 0x123445678 and write aa (4 byte) to the next 400 bytes
+ mf 0x123445678 aa ; Start at 0x123445678 and write aa (4 byte) to the next 1 byte
+ mf 0x123445678 ; Start at 0x123445678 and write 00 (4 byte) to the next 1 byte
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblMfillCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINTN Address;
+ UINTN EndAddress;
+ UINT32 Data;
+ UINTN Length;
+ UINTN Width;
+
+ if (Argc < 2) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address = AsciiStrHexToUintn (Argv[1]);
+ Data = (Argc > 2) ? (UINT32)AsciiStrHexToUintn (Argv[2]) : 0;
+ Width = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 4;
+ Length = (Argc > 4) ? AsciiStrHexToUintn (Argv[4]) : 1;
+
+ for (EndAddress = Address + (Length * Width); Address < EndAddress; Address += Width) {
+ if (Width == 4) {
+ MmioWrite32 (Address, Data);
+ } else if (Width == 2) {
+ MmioWrite32 (Address, (UINT16)Data);
+ } else {
+ MmioWrite32 (Address, (UINT8)Data);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+//
+// Strings for PCI Class code [2]
+//
+CHAR8 *gPciDevClass[] = {
+ "Old Device ",
+ "Mass storage ",
+ "Network ",
+ "Display ",
+ "Multimedia ",
+ "Memory controller ",
+ "Bridge device ",
+ "simple communications ",
+ "base system peripherals",
+ "Input devices ",
+ "Docking stations ",
+ "Processors ",
+ "serial bus ",
+};
+
+
+CHAR8 *gPciSerialClassCodes[] = {
+ "Mass storage ",
+ "Firewire ",
+ "ACCESS bus ",
+ "SSA ",
+ "USB "
+};
+
+
+/**
+ PCI Dump
+
+ Argv[0] - "pci"
+ Argv[1] - bus
+ Argv[2] - dev
+ Argv[3] - func
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblPciCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *Pci;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Seg;
+ UINTN Bus;
+ UINTN Dev;
+ UINTN Func;
+ UINTN BusArg;
+ UINTN DevArg;
+ UINTN FuncArg;
+ UINTN Index;
+ UINTN Count;
+ PCI_TYPE_GENERIC PciHeader;
+ PCI_TYPE_GENERIC *Header;
+ PCI_BRIDGE_CONTROL_REGISTER *Bridge;
+ PCI_DEVICE_HEADER_TYPE_REGION *Device;
+ PCI_DEVICE_INDEPENDENT_REGION *Hdr;
+ CHAR8 *Str;
+ UINTN ThisBus;
+
+
+ BusArg = (Argc > 1) ? AsciiStrDecimalToUintn (Argv[1]) : 0;
+ DevArg = (Argc > 2) ? AsciiStrDecimalToUintn (Argv[2]) : 0;
+ FuncArg = (Argc > 3) ? AsciiStrDecimalToUintn (Argv[3]) : 0;
+
+ Header = &PciHeader;
+
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);
+ if (EFI_ERROR (Status)) {
+ AsciiPrint ("No PCI devices found in the system\n");
+ return EFI_SUCCESS;
+ }
+
+ if (Argc == 1) {
+ // Dump all PCI devices
+ AsciiPrint ("BusDevFun VendorId DeviceId Device Class Sub-Class\n");
+ AsciiPrint ("_____________________________________________________________");
+ for (ThisBus = 0; ThisBus <= PCI_MAX_BUS; ThisBus++) {
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);
+ if (!EFI_ERROR (Status)) {
+ Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);
+ if (ThisBus != Bus) {
+ continue;
+ }
+ AsciiPrint ("\n%03d.%02d.%02d", Bus, Dev, Func);
+ Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), &PciHeader);
+ if (!EFI_ERROR (Status)) {
+ Hdr = &PciHeader.Bridge.Hdr;
+
+ if (Hdr->ClassCode[2] < sizeof (gPciDevClass)/sizeof (VOID *)) {
+ Str = gPciDevClass[Hdr->ClassCode[2]];
+ if (Hdr->ClassCode[2] == PCI_CLASS_SERIAL) {
+ if (Hdr->ClassCode[1] < sizeof (gPciSerialClassCodes)/sizeof (VOID *)) {
+ // print out Firewire or USB inplace of Serial Bus controllers
+ Str = gPciSerialClassCodes[Hdr->ClassCode[1]];
+ }
+ }
+ } else {
+ Str = "Unknown device ";
+ }
+ AsciiPrint (" 0x%04x 0x%04x %a 0x%02x", Hdr->VendorId, Hdr->DeviceId, Str, Hdr->ClassCode[1]);
+ }
+ if (Seg != 0) {
+ // Only print Segment if it is non zero. If you only have one PCI segment it is
+ // redundent to print it out
+ AsciiPrint (" Seg:%d", Seg);
+ }
+ }
+ }
+ }
+ AsciiPrint ("\n");
+ } else {
+ // Dump specific PCI device
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID **)&Pci);
+ if (!EFI_ERROR (Status)) {
+ Pci->GetLocation (Pci, &Seg, &Bus, &Dev, &Func);
+ if ((Bus == BusArg) && (Dev == DevArg) && (Func == FuncArg)) {
+ // Only print Segment if it is non zero. If you only have one PCI segment it is
+ // redundent to print it out
+ if (Seg != 0) {
+ AsciiPrint ("Seg:%d ", Seg);
+ }
+ AsciiPrint ("Bus:%d Dev:%d Func:%d ", Bus, Dev, Func);
+
+ Status = Pci->Pci.Read (Pci, EfiPciIoWidthUint32, 0, sizeof (PciHeader)/sizeof (UINT32), Header);
+ if (!EFI_ERROR (Status)) {
+ Hdr = &PciHeader.Bridge.Hdr;
+ if (IS_PCI_BRIDGE (&PciHeader.Bridge)) {
+ Bridge = &PciHeader.Bridge.Bridge;
+ AsciiPrint (
+ "PCI Bridge. Bus Primary %d Secondary %d Subordinate %d\n",
+ Bridge->PrimaryBus, Bridge->SecondaryBus, Bridge->SubordinateBus
+ );
+ AsciiPrint (" Bar 0: 0x%08x Bar 1: 0x%08x\n", Bridge->Bar[0], Bridge->Bar[1]);
+ } else {
+ Device = &PciHeader.Device.Device;
+ AsciiPrint (
+ "VendorId: 0x%04x DeviceId: 0x%04x SubSusVendorId: 0x%04x SubSysDeviceId: 0x%04x\n",
+ Hdr->VendorId, Hdr->DeviceId, Device->SubsystemVendorID, Device->SubsystemID
+ );
+ AsciiPrint (" Class Code: 0x%02x 0x%02x 0x%02x\n", Hdr->ClassCode[2], Hdr->ClassCode[1], Hdr->ClassCode[0]);
+ for (Count = 0; Count < 6; Count++) {
+ AsciiPrint (" Bar %d: 0x%08x\n", Count, Device->Bar[Count]);
+ }
+ }
+ }
+
+ AsciiPrint ("\n");
+ break;
+ }
+ }
+ }
+ }
+
+ FreePool (HandleBuffer);
+ return EFI_SUCCESS;
+}
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdPciDebugTemplate[] = {
+ "pci",
+ " [bus] [dev] [func]; Dump PCI",
+ NULL,
+ EblPciCmd
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwDebugTemplate[] =
+{
+ {
+ "md",
+ " [Addr] [Len] [1|2|4]; Memory Dump from Addr Len bytes",
+ NULL,
+ EblMdCmd
+ },
+ {
+ "mfill",
+ " Addr Len [data] [1|2|4]; Memory Fill Addr Len*(1|2|4) bytes of data(0)",
+ NULL,
+ EblMfillCmd
+ },
+};
+
+
+
+/**
+ Initialize the commands in this in this file
+**/
+VOID
+EblInitializemdHwDebugCmds (
+ VOID
+ )
+{
+ if (FeaturePcdGet (PcdEmbeddedHwDebugCmd)) {
+ EblAddCommands (mCmdHwDebugTemplate, sizeof (mCmdHwDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
+ }
+ if (FeaturePcdGet (PcdEmbeddedPciDebugCmd)) {
+ EblAddCommands (mCmdPciDebugTemplate, sizeof (mCmdPciDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
+ }
+}
+
diff --git a/EmbeddedPkg/Ebl/HwIoDebug.c b/EmbeddedPkg/Ebl/HwIoDebug.c new file mode 100644 index 0000000000..2d23e7c936 --- /dev/null +++ b/EmbeddedPkg/Ebl/HwIoDebug.c @@ -0,0 +1,153 @@ +/** @file
+ Hardware IO based debug commands
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Commands useful for debugging hardware. IO commands seperated out as not all
+ processor architectures support the IO command.
+
+**/
+
+#include "Ebl.h"
+
+
+
+/**
+ Read from IO space
+
+ Argv[0] - "ioread"
+ Argv[1] - Hex IO address
+ Argv[2] - IO Width [1|2|4] with a default of 1
+
+ ior 0x3f8 4 ;Do a 32-bit IO Read from 0x3f8
+ ior 0x3f8 1 ;Do a 8-bit IO Read from 0x3f8
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblIoReadCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINTN Width;
+ UINTN Port;
+ UINTN Data;
+
+ if (Argc < 2) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Port = AsciiStrHexToUintn (Argv[1]);
+ Width = (Argc > 2) ? AsciiStrHexToUintn (Argv[2]) : 1;
+
+ if (Width == 1) {
+ Data = IoRead8 (Port);
+ } else if (Width == 2) {
+ Data = IoRead16 (Port);
+ } else if (Width == 4) {
+ Data = IoRead32 (Port);
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AsciiPrint ("0x%04x = 0x%x", Port, Data);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Write to IO space
+
+ Argv[0] - "iowrite"
+ Argv[1] - Hex IO address
+ Argv[2] - Hex data to write
+ Argv[3] - IO Width [1|2|4] with a default of 1
+
+ iow 0x3f8 af 4 ;Do a 32-bit IO write of af to 0x3f8
+ iow 0x3f8 af ;Do an 8-bit IO write of af to 0x3f8
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblIoWriteCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINTN Width;
+ UINTN Port;
+ UINTN Data;
+
+ if (Argc < 3) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Port = AsciiStrHexToUintn (Argv[1]);
+ Data = AsciiStrHexToUintn (Argv[2]);
+ Width = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : 1;
+
+ if (Width == 1) {
+ IoWrite8 (Port, (UINT8)Data);
+ } else if (Width == 2) {
+ IoWrite16 (Port, (UINT16)Data);
+ } else if (Width == 4) {
+ IoWrite32 (Port, (UINT32)Data);
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+}
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdHwIoDebugTemplate[] =
+{
+ {
+ "ioread",
+ " Port [1|2|4]; IO read of width[1] byte(s) from Port",
+ NULL,
+ EblIoReadCmd
+ },
+ {
+ "iowrite",
+ " Port Data [1|2|4]; IO write Data of width[1] byte(s) to Port",
+ NULL,
+ EblIoWriteCmd
+ }
+};
+
+
+
+/**
+ Initialize the commands in this in this file
+**/
+VOID
+EblInitializemdHwIoDebugCmds (
+ VOID
+ )
+{
+ if (FeaturePcdGet (PcdEmbeddedIoEnable)) {
+ EblAddCommands (mCmdHwIoDebugTemplate, sizeof (mCmdHwIoDebugTemplate)/sizeof (EBL_COMMAND_TABLE));
+ }
+}
+
diff --git a/EmbeddedPkg/Ebl/Main.c b/EmbeddedPkg/Ebl/Main.c new file mode 100644 index 0000000000..5d1a37916f --- /dev/null +++ b/EmbeddedPkg/Ebl/Main.c @@ -0,0 +1,616 @@ +/** @file
+ Basic command line parser for EBL (Embedded Boot Loader)
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#include "Ebl.h"
+
+// Globals for command history processing
+INTN mCmdHistoryEnd = -1;
+INTN mCmdHistoryStart = -1;
+INTN mCmdHistoryCurrent = -1;
+CHAR8 mCmdHistory[MAX_CMD_HISTORY][MAX_CMD_LINE];
+CHAR8 *mCmdBlank = "";
+
+// Globals to remember current screen geometry
+UINTN gScreenColumns;
+UINTN gScreenRows;
+
+// Global to turn on/off breaking commands with prompts before they scroll the screen
+BOOLEAN gPageBreak = TRUE;
+
+VOID
+RingBufferIncrement (
+ IN INTN *Value
+ )
+{
+ *Value = *Value + 1;
+
+ if (*Value >= MAX_CMD_HISTORY) {
+ *Value = 0;
+ }
+}
+
+VOID
+RingBufferDecrement (
+ IN INTN *Value
+ )
+{
+ *Value = *Value - 1;
+
+ if (*Value < 0) {
+ *Value = MAX_CMD_HISTORY - 1;
+ }
+}
+
+/**
+ Save this command in the circular history buffer. Older commands are
+ overwritten with newer commands.
+
+ @param Cmd Command line to archive the history of.
+
+ @return None
+
+**/
+VOID
+SetCmdHistory (
+ IN CHAR8 *Cmd
+ )
+{
+ // Don't bother adding empty commands to the list
+ if (AsciiStrLen(Cmd) != 0) {
+
+ // First entry
+ if (mCmdHistoryStart == -1) {
+ mCmdHistoryStart = 0;
+ mCmdHistoryEnd = 0;
+ } else {
+ // Record the new command at the next index
+ RingBufferIncrement(&mCmdHistoryStart);
+
+ // If the next index runs into the end index, shuffle end back by one
+ if (mCmdHistoryStart == mCmdHistoryEnd) {
+ RingBufferIncrement(&mCmdHistoryEnd);
+ }
+ }
+
+ // Copy the new command line into the ring buffer
+ AsciiStrnCpy(&mCmdHistory[mCmdHistoryStart][0], Cmd, MAX_CMD_LINE);
+ }
+
+ // Reset the command history for the next up arrow press
+ mCmdHistoryCurrent = mCmdHistoryStart;
+}
+
+
+/**
+ Retreave data from the Command History buffer. Direction maps into up arrow
+ an down arrow on the command line
+
+ @param Direction Command forward or back
+
+ @return The Command history based on the Direction
+
+**/
+CHAR8 *
+GetCmdHistory (
+ IN UINT16 Direction
+ )
+{
+ CHAR8 *HistoricalCommand = NULL;
+
+ // No history yet?
+ if (mCmdHistoryCurrent == -1) {
+ HistoricalCommand = mCmdBlank;
+ goto Exit;
+ }
+
+ if (Direction == SCAN_UP) {
+ HistoricalCommand = &mCmdHistory[mCmdHistoryCurrent][0];
+
+ // if we just echoed the last command, hang out there, don't wrap around
+ if (mCmdHistoryCurrent == mCmdHistoryEnd) {
+ goto Exit;
+ }
+
+ // otherwise, back up by one
+ RingBufferDecrement(&mCmdHistoryCurrent);
+
+ } else if (Direction == SCAN_DOWN) {
+
+ // if we last echoed the start command, put a blank prompt out
+ if (mCmdHistoryCurrent == mCmdHistoryStart) {
+ HistoricalCommand = mCmdBlank;
+ goto Exit;
+ }
+
+ // otherwise increment the current pointer and return that command
+ RingBufferIncrement(&mCmdHistoryCurrent);
+ RingBufferIncrement(&mCmdHistoryCurrent);
+
+ HistoricalCommand = &mCmdHistory[mCmdHistoryCurrent][0];
+ RingBufferDecrement(&mCmdHistoryCurrent);
+ }
+
+Exit:
+ return HistoricalCommand;
+}
+
+
+/**
+ Parse the CmdLine and break it up into Argc (arg count) and Argv (array of
+ pointers to each argument). The Cmd buffer is altered and seperators are
+ converted to string terminators. This allows Argv to point into CmdLine.
+ A CmdLine can support multiple commands. The next command in the command line
+ is returned if it exists.
+
+ @param CmdLine String to parse for a set of commands
+ @param Argc Returns the number of arguments in the CmdLine current command
+ @param Argv Argc pointers to each string in CmdLine
+
+ @return Next Command in the command line or NULL if non exists
+**/
+CHAR8 *
+ParseArguments (
+ IN CHAR8 *CmdLine,
+ OUT UINTN *Argc,
+ OUT CHAR8 **Argv
+ )
+{
+ UINTN Arg;
+ CHAR8 *Char;
+ BOOLEAN LookingForArg;
+ BOOLEAN InQuote;
+
+ *Argc = 0;
+ if (AsciiStrLen (CmdLine) == 0) {
+ return NULL;
+ }
+
+ // Walk a single command line. A CMD_SEPERATOR allows mult commands on a single line
+ InQuote = FALSE;
+ LookingForArg = TRUE;
+ for (Char = CmdLine, Arg = 0; *Char != '\0'; Char++) {
+ if (!InQuote && *Char == CMD_SEPERATOR) {
+ break;
+ }
+
+ // Perform any text coversion here
+ if (*Char == '\t') {
+ // TAB to space
+ *Char = ' ';
+ }
+
+ if (LookingForArg) {
+ // Look for the beging of an Argv[] entry
+ if (*Char == '"') {
+ Argv[Arg++] = ++Char;
+ LookingForArg = FALSE;
+ InQuote = TRUE;
+ } else if (*Char != ' ') {
+ Argv[Arg++] = Char;
+ LookingForArg = FALSE;
+ }
+ } else {
+ // Looking for the terminator of an Argv[] entry
+ if ((InQuote && (*Char == '"')) || (!InQuote && (*Char == ' '))) {
+ *Char = '\0';
+ LookingForArg = TRUE;
+ }
+ }
+ }
+
+ *Argc = Arg;
+
+ if (*Char == CMD_SEPERATOR) {
+ // Replace the command delimeter with null and return pointer to next command line
+ *Char = '\0';
+ return ++Char;
+ }
+
+ return NULL;
+}
+
+
+/**
+ Return a keypress or optionally timeout if a timeout value was passed in.
+ An optional callback funciton is called evey second when waiting for a
+ timeout.
+
+ @param Key EFI Key information returned
+ @param TimeoutInSec Number of seconds to wait to timeout
+ @param CallBack Callback called every second during the timeout wait
+
+ @return EFI_SUCCESS Key was returned
+ @return EFI_TIMEOUT If the TimoutInSec expired
+
+**/
+EFI_STATUS
+EblGetCharKey (
+ IN OUT EFI_INPUT_KEY *Key,
+ IN UINTN TimeoutInSec,
+ IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN WaitCount;
+ UINTN WaitIndex;
+ EFI_EVENT WaitList[2];
+
+ WaitCount = 1;
+ WaitList[0] = gST->ConIn->WaitForKey;
+ if (TimeoutInSec != 0) {
+ // Create a time event for 1 sec duration if we have a timeout
+ gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &WaitList[1]);
+ gBS->SetTimer (WaitList[1], TimerPeriodic, EFI_SET_TIMER_TO_SECOND);
+ WaitCount++;
+ }
+
+ for (;;) {
+ Status = gBS->WaitForEvent (WaitCount, WaitList, &WaitIndex);
+ ASSERT_EFI_ERROR (Status);
+
+ switch (WaitIndex) {
+ case 0:
+ // Key event signaled
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);
+ if (!EFI_ERROR (Status)) {
+ if (WaitCount == 2) {
+ gBS->CloseEvent (WaitList[1]);
+ }
+ return EFI_SUCCESS;
+ }
+ break;
+
+ case 1:
+ // Periodic 1 sec timer signaled
+ TimeoutInSec--;
+ if (CallBack != NULL) {
+ // Call the users callback function if registered
+ CallBack (TimeoutInSec);
+ }
+ if (TimeoutInSec == 0) {
+ gBS->CloseEvent (WaitList[1]);
+ return EFI_TIMEOUT;
+ }
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ }
+}
+
+
+/**
+ This routine is used prevent command output data from scrolling off the end
+ of the screen. The global gPageBreak is used to turn on or off this feature.
+ If the CurrentRow is near the end of the screen pause and print out a prompt
+ If the use hits Q to quit return TRUE else for any other key return FALSE.
+ PrefixNewline is used to figure out if a newline is needed before the prompt
+ string. This depends on the last print done before calling this function.
+ CurrentRow is updated by one on a call or set back to zero if a prompt is
+ needed.
+
+ @param CurrentRow Used to figure out if its the end of the page and updated
+ @param PrefixNewline Did previous print issue a newline
+
+ @return TRUE if Q was hit to quit, FALSE in all other cases.
+
+**/
+BOOLEAN
+EblAnyKeyToContinueQtoQuit (
+ IN UINTN *CurrentRow,
+ IN BOOLEAN PrefixNewline
+ )
+{
+ EFI_INPUT_KEY InputKey;
+
+ if (!gPageBreak) {
+ // global disable for this feature
+ return FALSE;
+ }
+
+ if (*CurrentRow >= (gScreenRows - 2)) {
+ if (PrefixNewline) {
+ AsciiPrint ("\n");
+ }
+ AsciiPrint ("Any key to continue (Q to quit): ");
+ EblGetCharKey (&InputKey, 0, NULL);
+ AsciiPrint ("\n");
+
+ // Time to promt to stop the screen. We have to leave space for the prompt string
+ *CurrentRow = 0;
+ if (InputKey.UnicodeChar == 'Q' || InputKey.UnicodeChar == 'q') {
+ return TRUE;
+ }
+ } else {
+ *CurrentRow += 1;
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Set the text color of the EFI Console. If a zero is passed in reset to
+ default text/background color.
+
+ @param Attribute For text and background color
+
+**/
+VOID
+EblSetTextColor (
+ UINTN Attribute
+ )
+{
+ if (Attribute == 0) {
+ // Set the text color back to default
+ Attribute = (UINTN)PcdGet32 (PcdEmbeddedDefaultTextColor);
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, Attribute);
+}
+
+
+/**
+ Collect the keyboard input for a cmd line. Carage Return, New Line, or ESC
+ terminates the command line. You can edit the command line via left arrow,
+ delete and backspace and they all back up and erase the command line.
+ No edit of commnad line is possible without deletion at this time!
+ The up arrow and down arrow fill Cmd with information from the history
+ buffer.
+
+ @param Cmd Command line to return
+ @param CmdMaxSize Maximum size of Cmd
+
+ @return The Status of EblGetCharKey()
+
+**/
+EFI_STATUS
+GetCmd (
+ IN OUT CHAR8 *Cmd,
+ IN UINTN CmdMaxSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Index2;
+ CHAR8 Char;
+ CHAR8 *History;
+ EFI_INPUT_KEY Key;
+
+ for (Index = 0; Index < CmdMaxSize - 1;) {
+ Status = EblGetCharKey (&Key, 0, NULL);
+ if (EFI_ERROR (Status)) {
+ Cmd[Index] = '\0';
+ AsciiPrint ("\n");
+ return Status;
+ }
+
+ Char = (CHAR8)Key.UnicodeChar;
+ if ((Char == '\n') || (Char == '\r') || (Char == 0x7f)) {
+ Cmd[Index] = '\0';
+ if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) {
+ AsciiPrint ("\n\r");
+ }
+ return EFI_SUCCESS;
+ } else if ((Char == '\b') || (Key.ScanCode == SCAN_LEFT) || (Key.ScanCode == SCAN_DELETE)){
+ if (Index != 0) {
+ Index--;
+ //
+ // Update the display
+ //
+ AsciiPrint ("\b \b");
+ }
+ } else if ((Key.ScanCode == SCAN_UP) || Key.ScanCode == SCAN_DOWN) {
+ History = GetCmdHistory (Key.ScanCode);
+ //
+ // Clear display line
+ //
+ for (Index2 = 0; Index2 < Index; Index2++) {
+ AsciiPrint ("\b \b");
+ }
+ AsciiPrint (History);
+ Index = AsciiStrLen (History);
+ AsciiStrnCpy (Cmd, History, CmdMaxSize);
+ } else {
+ Cmd[Index++] = Char;
+ if (FixedPcdGetBool(PcdEmbeddedShellCharacterEcho) == TRUE) {
+ AsciiPrint ("%c", Char);
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Print the boot up banner for the EBL.
+**/
+VOID
+EblPrintStartupBanner (
+ VOID
+ )
+{
+ AsciiPrint ("Embedded Boot Loader (");
+ EblSetTextColor (EFI_YELLOW);
+ AsciiPrint ("EBL");
+ EblSetTextColor (0);
+ AsciiPrint (") prototype. Built at %a on %a\n",__TIME__, __DATE__);
+ AsciiPrint ("THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN 'AS IS' BASIS,\nWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\n");
+ AsciiPrint ("Please send feedback to dev@edk2.tianocore.org\n");
+}
+
+
+/**
+ Print the prompt for the EBL.
+**/
+VOID
+EblPrompt (
+ VOID
+ )
+{
+ EblSetTextColor (EFI_YELLOW);
+ AsciiPrint ((CHAR8 *)PcdGetPtr (PcdEmbeddedPrompt));
+ EblSetTextColor (0);
+ AsciiPrint ("%a", ">");
+}
+
+
+
+/**
+ Parse a command line and execute the commands. The ; seperator allows
+ multiple commands for each command line. Stop processing if one of the
+ commands returns an error.
+
+ @param CmdLine Command Line to process.
+ @param MaxCmdLineSize MaxSize of the Command line
+
+ @return EFI status of the Command
+
+**/
+EFI_STATUS
+ProcessCmdLine (
+ IN CHAR8 *CmdLine,
+ IN UINTN MaxCmdLineSize
+ )
+{
+ EFI_STATUS Status;
+ EBL_COMMAND_TABLE *Cmd;
+ CHAR8 *Ptr;
+ UINTN Argc;
+ CHAR8 *Argv[MAX_ARGS];
+
+ // Parse the command line. The loop processes commands seperated by ;
+ for (Ptr = CmdLine, Status = EFI_SUCCESS; Ptr != NULL;) {
+ Ptr = ParseArguments (Ptr, &Argc, Argv);
+ if (Argc != 0) {
+ Cmd = EblGetCommand (Argv[0]);
+ if (Cmd != NULL) {
+ // Execute the Command!
+ Status = Cmd->Command (Argc, Argv);
+ if (Status == EFI_ABORTED) {
+ // exit command so lets exit
+ break;
+ } else if (Status == EFI_TIMEOUT) {
+ // pause command got imput so don't process any more cmd on this cmd line
+ break;
+ } else if (EFI_ERROR (Status)) {
+ AsciiPrint ("%a returned %r error\n", Cmd->Name, Status);
+ // if any command fails stop processing CmdLine
+ break;
+ }
+ }
+ }
+ }
+
+ return Status;
+}
+
+
+
+/**
+ Embedded Boot Loader (EBL) - A simple EFI command line application for embedded
+ devices. PcdEmbeddedAutomaticBootCommand is a complied in commnad line that
+ gets executed automatically. The ; seperator allows multiple commands
+ for each command line.
+
+ @param ImageHandle EFI ImageHandle for this application.
+ @param SystemTable EFI system table
+
+ @return EFI status of the applicaiton
+
+**/
+EFI_STATUS
+EFIAPI
+EdkBootLoaderEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 CmdLine[MAX_CMD_LINE];
+ CHAR16 *CommandLineVariable = NULL;
+ CHAR16 *CommandLineVariableName = L"default-cmdline";
+ UINTN CommandLineVariableSize = 0;
+ EFI_GUID VendorGuid;
+
+ // Initialize tables of commnads
+ EblInitializeCmdTable ();
+ EblInitializeDeviceCmd ();
+ EblInitializemdHwDebugCmds ();
+ EblInitializemdHwIoDebugCmds ();
+ EblInitializeDirCmd ();
+ EblInitializeHobCmd ();
+ EblInitializeScriptCmd ();
+ EblInitializeExternalCmd ();
+ EblInitializeNetworkCmd();
+
+ if (FeaturePcdGet (PcdEmbeddedMacBoot)) {
+ // A MAC will boot in graphics mode, so turn it back to text here
+ // This protocol was removed from edk2. It is only an edk thing. We need to make our own copy.
+ // DisableQuietBoot ();
+
+ // Enable the biggest output screen size possible
+ gST->ConOut->SetMode (gST->ConOut, (UINTN)gST->ConOut->Mode->MaxMode - 1);
+
+ // Disable the 5 minute EFI watchdog time so we don't get automatically reset
+ gBS->SetWatchdogTimer (0, 0, 0, NULL);
+ }
+
+ // Save current screen mode
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &gScreenColumns, &gScreenRows);
+
+ EblPrintStartupBanner ();
+
+ // Parse command line and handle commands seperated by ;
+ // The loop prints the prompt gets user input and saves history
+
+ // Look for a variable with a default command line, otherwise use the Pcd
+ ZeroMem(&VendorGuid, sizeof(EFI_GUID));
+
+ Status = gRT->GetVariable(CommandLineVariableName, &VendorGuid, NULL, &CommandLineVariableSize, CommandLineVariable);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ CommandLineVariable = AllocatePool(CommandLineVariableSize);
+
+ Status = gRT->GetVariable(CommandLineVariableName, &VendorGuid, NULL, &CommandLineVariableSize, CommandLineVariable);
+ if (!EFI_ERROR(Status)) {
+ UnicodeStrToAsciiStr(CommandLineVariable, CmdLine);
+ }
+
+ FreePool(CommandLineVariable);
+ }
+
+ if (EFI_ERROR(Status)) {
+ AsciiStrCpy (CmdLine, (CHAR8 *)PcdGetPtr (PcdEmbeddedAutomaticBootCommand));
+ }
+
+ for (;;) {
+ Status = ProcessCmdLine (CmdLine, MAX_CMD_LINE);
+ if (Status == EFI_ABORTED) {
+ // if a command returns EFI_ABORTED then exit the EBL
+ EblShutdownExternalCmdTable ();
+ return EFI_SUCCESS;
+ }
+
+ // get the command line from the user
+ EblPrompt ();
+ GetCmd (CmdLine, MAX_CMD_LINE);
+ SetCmdHistory (CmdLine);
+ }
+}
+
+
diff --git a/EmbeddedPkg/Ebl/Network.c b/EmbeddedPkg/Ebl/Network.c new file mode 100644 index 0000000000..c566dda49a --- /dev/null +++ b/EmbeddedPkg/Ebl/Network.c @@ -0,0 +1,104 @@ +/** @file
+ EBL commands for Network Devices
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Ebl.h"
+
+EFI_STATUS
+ParseIp (
+ IN CHAR8 *String,
+ OUT EFI_IP_ADDRESS *Address
+ )
+{
+ Address->v4.Addr[0] = AsciiStrDecimalToUintn(String);
+ String = AsciiStrStr(String, ".") + 1;
+ Address->v4.Addr[1] = AsciiStrDecimalToUintn(String);
+ String = AsciiStrStr(String, ".") + 1;
+ Address->v4.Addr[2] = AsciiStrDecimalToUintn(String);
+ String = AsciiStrStr(String, ".") + 1;
+ Address->v4.Addr[3] = AsciiStrDecimalToUintn(String);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EblIpCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status = EFI_INVALID_PARAMETER;
+ EFI_MAC_ADDRESS Mac;
+ EFI_IP_ADDRESS Ip;
+
+ if (Argc == 1) {
+ // Get current IP/MAC
+
+ // Get current MAC address
+ Status = EblGetCurrentMacAddress (&Mac);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ AsciiPrint ("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", Mac.Addr[0], Mac.Addr[1], Mac.Addr[2], Mac.Addr[3], Mac.Addr[4], Mac.Addr[5]);
+
+ // Get current IP address
+ Status = EblGetCurrentIpAddress (&Ip);
+ if (EFI_ERROR(Status)) {
+ AsciiPrint("IP Address is not configured.\n");
+ Status = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ AsciiPrint("IP Address: %d.%d.%d.%d\n", Ip.v4.Addr[0], Ip.v4.Addr[1],Ip.v4.Addr[2], Ip.v4.Addr[3]);
+
+ } else if ((Argv[1][0] == 'r') && (Argc == 2)) {
+ // Get new address via dhcp
+ Status = EblPerformDHCP (TRUE);
+ } else if ((Argv[1][0] == 's') && (Argc == 3)) {
+ // Set static IP
+ Status = ParseIp (Argv[2], &Ip);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ Status = EblSetStationIp (&Ip, NULL);
+ }
+
+Exit:
+ return Status;
+}
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdNetworkTemplate[] =
+{
+ {
+ "ip",
+ " ; print current ip address\n\r [r]; request DHCP address\n\r [s] ipaddr; set static IP address",
+ NULL,
+ EblIpCmd
+ }
+};
+
+
+/**
+ Initialize the commands in this in this file
+**/
+VOID
+EblInitializeNetworkCmd (
+ VOID
+ )
+{
+ EblAddCommands (mCmdNetworkTemplate, sizeof (mCmdNetworkTemplate)/sizeof (EBL_COMMAND_TABLE));
+}
+
diff --git a/EmbeddedPkg/Ebl/Script.c b/EmbeddedPkg/Ebl/Script.c new file mode 100644 index 0000000000..2229005d1c --- /dev/null +++ b/EmbeddedPkg/Ebl/Script.c @@ -0,0 +1,126 @@ +/** @file
+ Script command allows the execution of commands from a text file
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name: EfiDevice.c
+
+**/
+
+#include "Ebl.h"
+
+
+/**
+ Execute the passed in file like a series of commands. The ; can be used on
+ a single line to indicate multiple commands per line. The Ascii text file
+ can contain any number of lines. The following line termination forms are
+ supported:
+ LF : Unix, Mac OS X*, BeOS
+ CR+LF: MS-DOS*, Microsoft Windows*
+ CR : Commodore, Apple II, and realy Mac OS
+ LF+CR: for simplicity and completeness
+
+ Argv[0] - "script"
+ Argv[1] - Device Name:path for the file to load
+
+ script fv1:\script.txt
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblScriptCmd (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ EFI_STATUS Status;
+ EFI_OPEN_FILE *File;
+ VOID *Address;
+ UINTN Size;
+ CHAR8 *Ptr;
+ CHAR8 *ScanPtr;
+ UINTN CmdLineSize;
+
+
+
+ if (Argc < 2) {
+ // file name required
+ return EFI_SUCCESS;
+ }
+
+ File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
+ if (File == NULL) {
+ AsciiPrint (" %a is not a valid path\n", Argv[1]);
+ return EFI_SUCCESS;
+ }
+
+ Status = EfiReadAllocatePool (File, &Address, &Size);
+ if (!EFI_ERROR (Status)) {
+ // Loop through each line in the text file
+ for (Ptr = (CHAR8 *)Address; (Ptr < (((CHAR8 *)Address) + Size)) && !EFI_ERROR (Status); Ptr += CmdLineSize) {
+ for (CmdLineSize = 0, ScanPtr = Ptr; ; CmdLineSize++, ScanPtr++) {
+ // look for the end of the line
+ if ((*ScanPtr == EBL_CR) || (*ScanPtr == EBL_LF)) {
+ // convert to NULL as this is what input routine would do
+ *ScanPtr = 0;
+ if ((*(ScanPtr + 1) == EBL_CR) || (*(ScanPtr + 1) == EBL_LF)) {
+ // if its a set get the 2nd EOL char
+ CmdLineSize++;
+ *(ScanPtr + 1) = 0;
+ }
+ CmdLineSize++;
+ break;
+ }
+
+ }
+
+ Status = ProcessCmdLine (Ptr, CmdLineSize);
+ }
+
+ FreePool (Address);
+ }
+
+ EfiClose (File);
+ return Status;
+}
+
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mScriptTemplate[] = {
+ {
+ "script",
+ " device:path; load an ascii file and execute it like commands",
+ NULL,
+ EblScriptCmd
+ }
+};
+
+
+/**
+ Initialize the commands in this in this file
+**/
+
+VOID
+EblInitializeScriptCmd (
+ VOID
+ )
+{
+ if (FeaturePcdGet (PcdEmbeddedScriptCmd)) {
+ EblAddCommands (mScriptTemplate, sizeof (mScriptTemplate)/sizeof (EBL_COMMAND_TABLE));
+ }
+}
+
diff --git a/EmbeddedPkg/EblExternCmd/EntryPointGlue.c b/EmbeddedPkg/EblExternCmd/EntryPointGlue.c new file mode 100644 index 0000000000..1e26fb5159 --- /dev/null +++ b/EmbeddedPkg/EblExternCmd/EntryPointGlue.c @@ -0,0 +1,152 @@ +/** @file
+ Glue code that contains the EFI entry point and converts it to an EBL
+ ASCII Argc, Argv sytle entry point
+
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#define CMD_SEPERATOR ';'
+#define MAX_ARGS 32
+
+EFI_STATUS
+EblMain (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ );
+
+
+///
+/// EdkExternCmdEntry() & ParseArguments() convert the standard EFI entry point
+/// into Argc, Argv form that calls EblMain().
+///
+
+
+/**
+ Parse the CmdLine and break it up into Argc (arg count) and Argv (array of
+ pointers to each argument). The Cmd buffer is altered and seperators are
+ converted to string terminators. This allows Argv to point into CmdLine.
+ A CmdLine can support multiple commands. The next command in the command line
+ is returned if it exists.
+
+ @param CmdLine String to parse for a set of commands
+ @param CmdLineSize Size of CmdLine in bytes
+ @param Argc Returns the number of arguments in the CmdLine current command
+ @param Argv Argc pointers to each string in CmdLine
+
+ @return Next Command in the command line or NULL if non exists
+**/
+VOID
+ParseArguments (
+ IN CHAR8 *CmdLine,
+ IN UINTN CmdLineSize,
+ OUT UINTN *Argc,
+ OUT CHAR8 **Argv
+ )
+{
+ UINTN Arg;
+ CHAR8 *Char;
+ BOOLEAN LookingForArg;
+ BOOLEAN InQuote;
+ UINTN Index;
+
+ *Argc = 0;
+ if ((CmdLineSize == 0) || (AsciiStrLen (CmdLine) == 0)) {
+ // basic error checking failed on the arguments
+ return;
+ }
+
+ // Walk a single command line. A CMD_SEPERATOR allows mult commands on a single line
+ InQuote = FALSE;
+ LookingForArg = TRUE;
+ for (Char = CmdLine, Arg = 0, Index = 0; *Char != '\0' && *Char != CMD_SEPERATOR; Char++, Index++) {
+ // Perform any text coversion here
+ if (*Char == '\t') {
+ // TAB to space
+ *Char = ' ';
+ }
+
+ if (LookingForArg) {
+ // Look for the beging of an Argv[] entry
+ if (*Char == '"') {
+ Argv[Arg++] = ++Char;
+ LookingForArg = FALSE;
+ InQuote = TRUE;
+ } else if (*Char != ' ') {
+ Argv[Arg++] = Char;
+ LookingForArg = FALSE;
+ }
+ } else {
+ // Looking for the terminator of an Argv[] entry
+ if ((InQuote && (*Char == '"')) || (!InQuote && (*Char == ' '))) {
+ *Char = '\0';
+ LookingForArg = TRUE;
+ }
+ }
+
+ if ((Arg >= MAX_ARGS) || (Index > CmdLineSize)) {
+ // Error check buffer and exit since it does not look valid
+ break;
+ }
+ }
+
+ *Argc = Arg;
+
+ if (*Char == CMD_SEPERATOR) {
+ // Replace the command delimeter with null
+ *Char = '\0';
+ }
+
+ return;
+}
+
+
+
+
+/**
+ Embedded Boot Loader (EBL) - A simple EFI command line application for embedded
+ devices. PcdEmbeddedAutomaticBootCommand is a complied in commnad line that
+ gets executed automatically. The ; seperator allows multiple commands
+ for each command line.
+
+ @param ImageHandle EFI ImageHandle for this application.
+ @param SystemTable EFI system table
+
+ @return EFI status of the applicaiton
+
+**/
+EFI_STATUS
+EFIAPI
+EdkExternCmdEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
+ UINTN Argc;
+ CHAR8 *Argv[MAX_ARGS];
+
+ Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);
+ if (EFI_ERROR (Status)) {
+ Argc = 0;
+ } else {
+ // Looks like valid commands were passed in.
+ ParseArguments (ImageInfo->LoadOptions, ImageInfo->LoadOptionsSize, &Argc, Argv);
+ }
+
+ return EblMain (Argc, Argv);
+}
+
+
diff --git a/EmbeddedPkg/EblExternCmd/Main.c b/EmbeddedPkg/EblExternCmd/Main.c new file mode 100644 index 0000000000..04f1eab600 --- /dev/null +++ b/EmbeddedPkg/EblExternCmd/Main.c @@ -0,0 +1,52 @@ +/** @file
+ Example of an external EBL command. It's loaded via EBL start command.
+ Argc and Argv are passed in via "" of the EBL command line.
+
+ Start fs0:\EdkExternCmd.efi "Argv[0] Argv[1] 2"
+
+ will launch this command with
+ Argv[0] = "Argv[0]"
+ Argv[1] = "Argv[2]"
+ Argv[2] = "3"
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+
+/**
+ Entry point with Argc, Argv. Put your code here.
+
+ @param Argc Number of command arguments in Argv
+ @param Argv Array of strings that represent the parsed command line.
+ Argv[0] is the comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+EblMain (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ )
+{
+ UINTN Index;
+
+ AsciiPrint ("Hello World\n");
+ for (Index = 0; Index < Argc; Index++) {
+ AsciiPrint ("Argv[%d] = %a\n", Index, Argv[Index]);
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.c b/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.c new file mode 100644 index 0000000000..66ebe67a92 --- /dev/null +++ b/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.c @@ -0,0 +1,82 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include <Protocol/MonotonicCounter.h>
+
+UINT64 gCurrentMonotonicCount = 0;
+
+EFI_STATUS
+EFIAPI
+GetNextMonotonicCount (
+ OUT UINT64 *Count
+ )
+{
+ if (Count == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Count = gCurrentMonotonicCount++;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetNextHighMonotonicCount (
+ OUT UINT32 *HighCount
+ )
+{
+ if (HighCount == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ gCurrentMonotonicCount += 0x0000000100000000ULL;
+
+ *HighCount = RShiftU64 (gCurrentMonotonicCount, 32) & 0xFFFFFFFF;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+MonotonicCounterDriverInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle = NULL;
+
+ // Make sure the Monotonic Counter Architectural Protocol is not already installed in the system
+ ASSERT_PROTOCOL_ALREADY_INSTALLED(NULL, &gEfiMonotonicCounterArchProtocolGuid);
+
+ // Fill in the EFI Boot Services and EFI Runtime Services Monotonic Counter Fields
+ gBS->GetNextMonotonicCount = GetNextMonotonicCount;
+ gRT->GetNextHighMonotonicCount = GetNextHighMonotonicCount;
+
+ // Install the Monotonic Counter Architctural Protocol onto a new handle
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiMonotonicCounterArchProtocolGuid, NULL,
+ NULL
+ );
+ return Status;
+}
diff --git a/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf b/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf new file mode 100644 index 0000000000..8508ac53a3 --- /dev/null +++ b/EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf @@ -0,0 +1,29 @@ +#%HEADER%
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EmbeddedMonotonicCounter
+ FILE_GUID = FCABE6A7-7953-4A84-B7EC-D29E89B62E87
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = MonotonicCounterDriverInitialize
+
+[Sources.common]
+ EmbeddedMonotonicCounter.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiMonotonicCounterArchProtocolGuid
+
+[Depex]
+ TRUE
+
diff --git a/EmbeddedPkg/EmbeddedPkg.dec b/EmbeddedPkg/EmbeddedPkg.dec new file mode 100644 index 0000000000..22ee365e7b --- /dev/null +++ b/EmbeddedPkg/EmbeddedPkg.dec @@ -0,0 +1,126 @@ +#%HEADER%
+#/** @file
+# Framework Module Development Environment Industry Standards
+#
+# This Package provides headers and libraries that conform to EFI/PI Industry standards.
+# Copyright (c) 2007, Intel Corporation.
+#
+# All rights reserved.
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = EmbeddedPkg
+ PACKAGE_GUID = dea8e498-7e1b-47c1-b6fa-4bc04092587e
+ PACKAGE_VERSION = 0.1
+
+
+################################################################################
+#
+# Include Section - list of Include Paths that are provided by this package.
+# Comments are used for Keywords and Module Types.
+#
+# Supported Module Types:
+# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
+#
+################################################################################
+[Includes.common]
+ Include # Root include for the package
+
+[LibraryClasses.common]
+ EfiFileLib|Include/Library/EfiFileLib.h
+ PrePiLib|Include/Library/PrePiLib.h
+ RealTimeClockLib|Include/Library/RealTimeClockLib.h
+ EfiResetSystemLib|Include/Library/EfiResetSystemLib.h
+ EblCmdLib|Include/Library/EblCmdLib.h
+ EblAddExternalCommandLib|Library/EblAddExternalCommandLib.h
+ EblNetworkLib|Library/EblNetworkLib.h
+ GdbSerialLib|Include/Library/GdbSerialLib.h
+
+
+[Guids.common]
+ gEmbeddedTokenSpaceGuid = { 0xe0d8ca17, 0x4276, 0x4386, { 0xbb, 0x79, 0x48, 0xcb, 0x81, 0x3d, 0x3c, 0x4f }}
+
+[Protocols.common]
+ gHardwareInterruptProtocolGuid = { 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } }
+ gEfiDebugSupportPeriodicCallbackProtocolGuid = { 0x9546e07c, 0x2cbb, 0x4c88, { 0x98, 0x6c, 0xcd, 0x34, 0x10, 0x86, 0xf0, 0x44 } }
+ gEfiEblAddCommandProtocolGuid = { 0xaeda2428, 0x9a22, 0x4637, { 0x9b, 0x21, 0x54, 0x5e, 0x28, 0xfb, 0xb8, 0x29 } }
+ gEmbeddedDeviceGuid = { 0xbf4b9d10, 0x13ec, 0x43dd, { 0x88, 0x80, 0xe9, 0xb, 0x71, 0x8f, 0x27, 0xde } }
+ gEmbeddedExternalDeviceProtocolGuid = { 0x735F8C64, 0xD696, 0x44D0, { 0xBD, 0xF2, 0x44, 0x7F, 0xD0, 0x5A, 0x54, 0x06 }}
+ gEmbeddedGpioProtocolGuid = { 0x17a0a3d7, 0xc0a5, 0x4635, { 0xbb, 0xd5, 0x07, 0x21, 0x87, 0xdf, 0xe2, 0xee }}
+
+[PcdsFeatureFlag.common]
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|FALSE|BOOLEAN|0x00000001
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE|BOOLEAN|0x00000002
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE|BOOLEAN|0x00000003
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE|BOOLEAN|0x00000004
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE|BOOLEAN|0x00000005
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE|BOOLEAN|0x00000006
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|FALSE|BOOLEAN|0x00000041
+ gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|FALSE|BOOLEAN|0x0000001b
+ gEmbeddedTokenSpaceGuid.PcdCacheEnable|FALSE|BOOLEAN|0x00000042
+ gEmbeddedTokenSpaceGuid.PcdGdbSerial|FALSE|BOOLEAN|0x0000004d
+
+
+[PcdsFixedAtBuild.common]
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|L""|VOID*|0x00000007
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07|UINT32|0x00000008
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000|UINT32|0x00000009
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedPrompt|"Ebl"|VOID*|0x00000034
+
+ gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|131072|UINT32|0x00000040
+ gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0|UINT32|0x0000000b
+ gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|131072|UINT32|0x0000000c
+ gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0|UINT32|0x000000d
+ gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0|UINT32|0x000000e
+ gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0|UINT32|0x0000000f
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32|UINT8|0x00000010
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0|UINT8|0x00000011
+
+ gEmbeddedTokenSpaceGuid.PcdFlashFvMainBase|0x0|UINT32|0x00000043
+ gEmbeddedTokenSpaceGuid.PcdFlashFvMainOffset|0x0|UINT32|0x00000044
+ gEmbeddedTokenSpaceGuid.PcdFlashFvMainSize|0x0|UINT32|0x000000045
+
+
+# Used to help reduce fragmentation in the EFI memory map
+# EFI Pages (4K) are the units used
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0|UINT32|0x00000012
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0|UINT32|0x00000013
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0|UINT32|0x00000014
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0|UINT32|0x00000015
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0|UINT32|0x00000016
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|0|UINT32|0x00000017
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|0|UINT32|0x00000018
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|0|UINT32|0x00000019
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0|UINT32|0x0000001a
+
+ gEmbeddedTokenSpaceGuid.PcdTimerBaseAddress|0x3c700000|UINT32|0x0000001c
+ gEmbeddedTokenSpaceGuid.PcdTimerVector|7|UINT32|0x0000001d
+ gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000|UINT32|0x0000001e
+ gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress|0x38e00000|UINT32|0x0000001f
+
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress|0xffff0000|UINT32|0x00000030
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize|0x0000000|UINT32|0x00000031
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedPerformanceCounterFreqencyInHz|0x0000000|UINT64|0x00000032
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedFdPerformanceCounterPeriodInNanoseconds|0x0000000|UINT32|0x00000033
+
+# Shell characteristics
+ gEmbeddedTokenSpaceGuid.PcdEmbeddedShellCharacterEcho|TRUE|BOOLEAN|0x00000046
+
+ gEmbeddedTokenSpaceGuid.PcdGdbBaudRate|115200|UINT64|0x00000047
+ gEmbeddedTokenSpaceGuid.PcdGdbDataBits|8|UINT8|0x00000048
+ gEmbeddedTokenSpaceGuid.PcdGdbParity|1|UINT8|0x00000049
+ gEmbeddedTokenSpaceGuid.PcdGdbStopBits|1|UINT8|0x0000004a
+ gEmbeddedTokenSpaceGuid.PcdGdbUartPort|0x3f8|UINT32|0x0000004b
+ gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount|10000000|UINT32|0x0000004c
+
+
+
diff --git a/EmbeddedPkg/EmbeddedPkg.dsc b/EmbeddedPkg/EmbeddedPkg.dsc new file mode 100644 index 0000000000..d1a4ed8da3 --- /dev/null +++ b/EmbeddedPkg/EmbeddedPkg.dsc @@ -0,0 +1,266 @@ +#%HEADER% +#/** @file +# Embedded Package +# +# +# Copyright (c) 2007, Intel Corporation +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = Embedded + PLATFORM_GUID = 8DBB580B-CF89-4D57-95C6-DFE96C44686E + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/Embedded + SUPPORTED_ARCHITECTURES = IA32|X64|IPF|ARM + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = EmbeddedPkg/EmbeddedPkg.fdf + + +################################################################################ +# +# SKU Identification section - list of all SKU IDs supported by this +# Platform. +# +################################################################################ +[SkuIds] + 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required. + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ +[LibraryClasses.common] +# DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + + + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + EfiFileLib|EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf + + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf + + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + + SerialPortLib|EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf + RealTimeClockLib|EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf + EfiResetSystemLib|EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf + GdbSerialLib|EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf + + + # + # Need to change this for IPF + # + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + EblCmdLib|EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf + + EblNetworkLib|EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf + + +[LibraryClasses.common.DXE_DRIVER] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + + +[LibraryClasses.common.UEFI_APPLICATION] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + +[LibraryClasses.common.SEC] + ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + +[LibraryClasses.ARM] + SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf + +################################################################################ +# +# Pcd Section - list of all PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable|FALSE + gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|FALSE + gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|FALSE + + # + # Control what commands are supported from the UI + # Turn these on and off to add features or save size + # + gEmbeddedTokenSpaceGuid.PcdEmbeddedMacBoot|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedDirCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHobCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedHwDebugCmd|TRUE + gEmbeddedTokenSpaceGuid.PcdEmbeddedIoEnable|FALSE + gEmbeddedTokenSpaceGuid.PcdEmbeddedScriptCmd|FALSE + gEmbeddedTokenSpaceGuid.PcdEmbeddedPciDebugCmd|TRUE + + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|FALSE + + +[PcdsFixedAtBuild.common] + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000 + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06 + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000 + gEfiMdePkgTokenSpaceGuid.PcdFSBClock|200000000 + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320 + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000 + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000 + gEfiMdePkgTokenSpaceGuid.PcdFSBClock|200000000 + gEmbeddedTokenSpaceGuid.PcdEmbeddedAutomaticBootCommand|L""|VOID*|2 + gEmbeddedTokenSpaceGuid.PcdEmbeddedDefaultTextColor|0x07 + gEmbeddedTokenSpaceGuid.PcdEmbeddedMemVariableStoreSize|0x10000 + + gEmbeddedTokenSpaceGuid.PcdPrePiHobBase|0 + gEmbeddedTokenSpaceGuid.PcdPrePiStackBase|0 + gEmbeddedTokenSpaceGuid.PcdPrePiStackSize|0 + gEmbeddedTokenSpaceGuid.PcdPrePiTempMemorySize|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvBaseAddress|0 + gEmbeddedTokenSpaceGuid.PcdPrePiBfvSize|0 + +# +# Optinal feature to help prevent EFI memory map fragments +# Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob +# Values are in EFI Pages (4K). DXE Core will make sure that +# at least this much of each type of memory can be allocated +# from a single memory range. This way you only end up with +# maximum of two fragements for each type in the memory map +# (the memory used, and the free memory that was prereserved +# but not used). +# + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0 + +# +# Timer config for this platform +# + gEmbeddedTokenSpaceGuid.PcdTimerBaseAddress|0x3c700000 + gEmbeddedTokenSpaceGuid.PcdTimerVector|7 + gEmbeddedTokenSpaceGuid.PcdTimerPeriod|100000 + + +[PcdsFixedAtBuild.ARM] + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0 + +[PcdsFixedAtBuild.IA32] + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|36 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16 + +[PcdsFixedAtBuild.X64] + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|52 + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16 + + + +[PcdsFixedAtBuild.IPF] + gEfiMdePkgTokenSpaceGuid.PcdIoBlockBaseAddressForIpf|0x0ffffc000000 + +# +# This makes it so you can source level debug with NT32. VC++ debugger limitiation! +# +#[BuildOptions] +# DEBUG_*_IA32_DLINK_FLAGS = /EXPORT:InitializeDriver=$(IMAGE_ENTRY_POINT) /ALIGN:4096 /SUBSYSTEM:CONSOLE +# RELEASE_*_IA32_DLINK_FLAGS = /ALIGN:4096 +# *_*_IA32_CC_FLAGS = /D EFI_SPECIFICATION_VERSION=0x0002000A /D TIANO_RELEASE_VERSION=0x00080006 + + +################################################################################ +# +# Components Section - list of all Modules needed by this Platform +# +################################################################################ +[Components.common] + EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf + EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf + EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf + EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf # ApplePkg + EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf # ApplePkg + EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf + EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf + EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf + +####ArmPkg/Library/UncachedMemoryAllocationLib/UncachedMemoryAllocationLib.inf ??? + + + EmbeddedPkg/Ebl/Ebl.inf +#### EmbeddedPkg/EblExternCmd/EblExternCmd.inf + EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf + EmbeddedPkg/GdbStub/GdbStub.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + EmbeddedPkg/SerialDxe/SerialDxe.inf + EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf + EmbeddedPkg/TemplateBds/TemplateBds.inf + EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf + EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf + EmbeddedPkg/TemplateSec/TemplateSec.inf + EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf + + + + diff --git a/EmbeddedPkg/EmbeddedPkg.fdf b/EmbeddedPkg/EmbeddedPkg.fdf new file mode 100644 index 0000000000..67e329e89d --- /dev/null +++ b/EmbeddedPkg/EmbeddedPkg.fdf @@ -0,0 +1,141 @@ +# This is Ebl FDF file
+#
+# Copyright (c) 2008, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+
+################################################################################
+#
+# FV Section
+#
+# [FV] section is used to define what components or modules are placed within a flash
+# device file. This section also defines order the components and modules are positioned
+# within the image. The [FV] section consists of define statements, set statements and
+# module statements.
+#
+################################################################################
+[FV.FvLoad]
+FvAlignment = 16 #FV alignment and FV attributes setting.
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+################################################################################
+#
+# The INF statements point to module INF files, which will be placed into this FV image.
+# Parsing tools will scan the INF file to determine the type of component or module.
+# The component or module type is used to reference the standard rules
+# defined elsewhere in the FDF file.
+#
+# The format for INF statements is:
+# INF $(PathAndInfFileName)
+#
+################################################################################
+INF EmbeddedPkg/Ebl/Ebl.inf
+
+################################################################################
+#
+# Rules are use with the [FV] section's module INF type to define
+# how an FFS file is created for a given INF file. The following Rule are the default
+# rules for the different module type. User can add the customized rules to define the
+# content of the FFS file.
+#
+################################################################################
+
+
+############################################################################
+# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section #
+############################################################################
+#
+#[Rule.Common.DXE_DRIVER]
+# FILE DRIVER = $(NAMED_GUID) {
+# DXE_DEPEX DXE_DEPEX Optional |.depex
+# COMPRESS PI_STD {
+# GUIDED {
+# PE32 PE32 |.efi
+# UI STRING="$(MODULE_NAME)" Optional
+# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+# }
+# }
+# }
+#
+############################################################################
+
+[Rule.Common.SEC]
+ FILE SEC = $(NAMED_GUID) {
+ PE32 PE32 |.efi
+ }
+
+[Rule.Common.PEI_CORE]
+ FILE PEI_CORE = $(NAMED_GUID) {
+ PE32 PE32 |.efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ }
+
+[Rule.Common.PEIM]
+ FILE PEIM = $(NAMED_GUID) {
+ PEI_DEPEX PEI_DEPEX Optional |.depex
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ }
+
+[Rule.Common.PEIM.TIANOCOMPRESSED]
+ FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 {
+ PEI_DEPEX PEI_DEPEX Optional |.depex
+ GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ }
+ }
+
+[Rule.Common.DXE_CORE]
+ FILE DXE_CORE = $(NAMED_GUID) {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ }
+
+[Rule.Common.UEFI_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ }
+
+[Rule.Common.DXE_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ }
+
+[Rule.Common.UEFI_APPLICATION]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ }
diff --git a/EmbeddedPkg/GdbStub/Arm/Processor.c b/EmbeddedPkg/GdbStub/Arm/Processor.c new file mode 100644 index 0000000000..e620d344e6 --- /dev/null +++ b/EmbeddedPkg/GdbStub/Arm/Processor.c @@ -0,0 +1,717 @@ +/** @file
+ Processor specific parts of the GDB stub
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+/** @file
+
+ Copyright (c) 2008, Apple, Inc
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <GdbStubInternal.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/PrintLib.h>
+
+//
+// Array of exception types that need to be hooked by the debugger
+// (efi, gdb) //efi number
+//
+EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
+ { EXCEPT_ARM_SOFTWARE_INTERRUPT, GDB_SIGTRAP }
+// { EXCEPT_ARM_UNDEFINED_INSTRUCTION, GDB_SIGTRAP },
+// { EXCEPT_ARM_PREFETCH_ABORT, GDB_SIGTRAP },
+// { EXCEPT_ARM_DATA_ABORT, GDB_SIGEMT },
+// { EXCEPT_ARM_RESERVED, GDB_SIGILL }
+};
+
+// Shut up some annoying RVCT warnings
+#ifdef __CC_ARM
+#pragma diag_suppress 1296
+#endif
+
+UINTN gRegisterOffsets[] = {
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R0),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R1),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R2),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R3),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R4),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R5),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R6),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R7),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R8),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R9),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R10),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R11),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, R12),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, SP),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, LR),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, PC),
+ 0x00000F01, // f0
+ 0x00000F02,
+ 0x00000F03,
+ 0x00000F11, // f1
+ 0x00000F12,
+ 0x00000F13,
+ 0x00000F21, // f2
+ 0x00000F22,
+ 0x00000F23,
+ 0x00000F31, // f3
+ 0x00000F32,
+ 0x00000F33,
+ 0x00000F41, // f4
+ 0x00000F42,
+ 0x00000F43,
+ 0x00000F51, // f5
+ 0x00000F52,
+ 0x00000F53,
+ 0x00000F61, // f6
+ 0x00000F62,
+ 0x00000F63,
+ 0x00000F71, // f7
+ 0x00000F72,
+ 0x00000F73,
+ 0x00000FFF, // fps
+ 0x00000FFF,
+ 0x00000FFF,
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_ARM, CPSR)
+};
+
+// restore warnings for RVCT
+#ifdef __CC_ARM
+#pragma diag_default 1296
+#endif
+
+/**
+ Return the number of entries in the gExceptionType[]
+
+ @retval UINTN, the number of entries in the gExceptionType[] array.
+ **/
+UINTN
+MaxEfiException (
+ VOID
+ )
+{
+ return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
+}
+
+
+/**
+ Return the number of entries in the gRegisters[]
+
+ @retval UINTN, the number of entries (registers) in the gRegisters[] array.
+ **/
+UINTN
+MaxRegisterCount (
+ VOID
+ )
+{
+ return sizeof (gRegisterOffsets)/sizeof (UINTN);
+}
+
+
+/**
+ Check to see if the ISA is supported.
+ ISA = Instruction Set Architecture
+
+ @retval TRUE if Isa is supported
+
+**/
+BOOLEAN
+CheckIsa (
+ IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
+ )
+{
+ if (Isa == IsaArm) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/**
+ This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
+ It is, by default, set to find the register pointer of the ARM member
+ @param SystemContext Register content at time of the exception
+ @param RegNumber The register to which we want to find a pointer
+ @retval the pointer to the RegNumber-th pointer
+ **/
+UINTN *
+FindPointerToRegister(
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN RegNumber
+ )
+{
+ UINT8 *TempPtr;
+ ASSERT(gRegisterOffsets[RegNumber] < 0xF00);
+ TempPtr = ((UINT8 *)SystemContext.SystemContextArm) + gRegisterOffsets[RegNumber];
+ return (UINT32 *)TempPtr;
+}
+
+
+/**
+ Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
+ @param SystemContext Register content at time of the exception
+ @param RegNumber the number of the register that we want to read
+ @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
+ @retval the pointer to the next character of the output buffer that is available to be written on.
+ **/
+CHAR8 *
+BasicReadRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN RegNumber,
+ IN CHAR8 *OutBufPtr
+ )
+{
+ UINTN RegSize;
+ CHAR8 Char;
+
+ if (gRegisterOffsets[RegNumber] > 0xF00) {
+ AsciiSPrint(OutBufPtr, 9, "00000000");
+ OutBufPtr += 8;
+ return OutBufPtr;
+ }
+
+ RegSize = 0;
+ while (RegSize < 32) {
+ Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
+ if ((Char >= 'A') && (Char <= 'F')) {
+ Char = Char - 'A' + 'a';
+ }
+ *OutBufPtr++ = Char;
+
+ Char = mHexToStr[(UINT8)((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];
+ if ((Char >= 'A') && (Char <= 'F')) {
+ Char = Char - 'A' + 'a';
+ }
+ *OutBufPtr++ = Char;
+
+ RegSize = RegSize + 8;
+ }
+ return OutBufPtr;
+}
+
+
+/** ‘p n’
+ Reads the n-th register's value into an output buffer and sends it as a packet
+ @param SystemContext Register content at time of the exception
+ @param InBuffer Pointer to the input buffer received from gdb server
+ **/
+VOID
+ReadNthRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *InBuffer
+ )
+{
+ UINTN RegNumber;
+ CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq)
+ CHAR8 *OutBufPtr; // pointer to the output buffer
+
+ RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
+
+ if (RegNumber >= MaxRegisterCount()) {
+ SendError (GDB_EINVALIDREGNUM);
+ return;
+ }
+
+ OutBufPtr = OutBuffer;
+ OutBufPtr = BasicReadRegister (SystemContext, RegNumber, OutBufPtr);
+
+ *OutBufPtr = '\0'; // the end of the buffer
+ SendPacket(OutBuffer);
+}
+
+
+/** ‘g’
+ Reads the general registers into an output buffer and sends it as a packet
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+EFIAPI
+ReadGeneralRegisters (
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINTN Index;
+ CHAR8 *OutBuffer;
+ CHAR8 *OutBufPtr;
+ UINTN RegisterCount = MaxRegisterCount();
+
+ // It is not safe to allocate pool here....
+ OutBuffer = AllocatePool((RegisterCount * 8) + 1); // 8 bytes per register in string format plus a null to terminate
+ OutBufPtr = OutBuffer;
+ for (Index = 0; Index < RegisterCount; Index++) {
+ OutBufPtr = BasicReadRegister (SystemContext, Index, OutBufPtr);
+ }
+
+ *OutBufPtr = '\0';
+ SendPacket(OutBuffer);
+ FreePool(OutBuffer);
+}
+
+
+/**
+ Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
+ @param SystemContext Register content at time of the exception
+ @param RegNumber the number of the register that we want to write
+ @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
+ @retval the pointer to the next character of the input buffer that can be used
+ **/
+CHAR8
+*BasicWriteRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN RegNumber,
+ IN CHAR8 *InBufPtr
+ )
+{
+ UINTN RegSize;
+ UINTN TempValue; // the value transferred from a hex char
+ UINT32 NewValue; // the new value of the RegNumber-th Register
+
+ if (gRegisterOffsets[RegNumber] > 0xF00) {
+ return InBufPtr + 8;
+ }
+
+ NewValue = 0;
+ RegSize = 0;
+ while (RegSize < 32) {
+ TempValue = HexCharToInt(*InBufPtr++);
+
+ if ((INTN)TempValue < 0) {
+ SendError (GDB_EBADMEMDATA);
+ return NULL;
+ }
+
+ NewValue += (TempValue << (RegSize+4));
+ TempValue = HexCharToInt(*InBufPtr++);
+
+ if ((INTN)TempValue < 0) {
+ SendError (GDB_EBADMEMDATA);
+ return NULL;
+ }
+
+ NewValue += (TempValue << RegSize);
+ RegSize = RegSize + 8;
+ }
+ *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;
+ return InBufPtr;
+}
+
+
+/** ‘P n...=r...’
+ Writes the new value of n-th register received into the input buffer to the n-th register
+ @param SystemContext Register content at time of the exception
+ @param InBuffer Ponter to the input buffer received from gdb server
+ **/
+VOID
+WriteNthRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *InBuffer
+ )
+{
+ UINTN RegNumber;
+ CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
+ CHAR8 *RegNumBufPtr;
+ CHAR8 *InBufPtr; // pointer to the input buffer
+
+ // find the register number to write
+ InBufPtr = &InBuffer[1];
+ RegNumBufPtr = RegNumBuffer;
+ while (*InBufPtr != '=') {
+ *RegNumBufPtr++ = *InBufPtr++;
+ }
+ *RegNumBufPtr = '\0';
+ RegNumber = AsciiStrHexToUintn (RegNumBuffer);
+
+ // check if this is a valid Register Number
+ if (RegNumber >= MaxRegisterCount()) {
+ SendError (GDB_EINVALIDREGNUM);
+ return;
+ }
+ InBufPtr++; // skips the '=' character
+ BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
+ SendSuccess();
+}
+
+
+/** ‘G XX...’
+ Writes the new values received into the input buffer to the general registers
+ @param SystemContext Register content at time of the exception
+ @param InBuffer Pointer to the input buffer received from gdb server
+ **/
+
+VOID
+EFIAPI
+WriteGeneralRegisters (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *InBuffer
+ )
+{
+ UINTN i;
+ CHAR8 *InBufPtr; /// pointer to the input buffer
+ UINTN MinLength;
+ UINTN RegisterCount = MaxRegisterCount();
+
+ MinLength = (RegisterCount * 8) + 1; // 'G' plus the registers in ASCII format
+
+ if (AsciiStrLen(InBuffer) < MinLength) {
+ //Bad message. Message is not the right length
+ SendError (GDB_EBADBUFSIZE);
+ return;
+ }
+
+ InBufPtr = &InBuffer[1];
+
+ // Read the new values for the registers from the input buffer to an array, NewValueArray.
+ // The values in the array are in the gdb ordering
+ for(i = 0; i < RegisterCount; i++) {
+ InBufPtr = BasicWriteRegister (SystemContext, i, InBufPtr);
+ }
+
+ SendSuccess ();
+}
+
+// What about Thumb?
+// Use SWI 0xdbdbdb as the debug instruction
+#define GDB_ARM_BKPT 0xefdbdbdb
+
+BOOLEAN mSingleStepActive = FALSE;
+UINT32 mSingleStepPC;
+UINT32 mSingleStepData;
+UINTN mSingleStepDataSize;
+
+typedef struct {
+ LIST_ENTRY Link;
+ UINT64 Signature;
+ UINT32 Address;
+ UINT32 Instruction;
+} ARM_SOFTWARE_BREAKPOINT;
+
+#define ARM_SOFTWARE_BREAKPOINT_SIGNATURE SIGNATURE_64('A', 'R', 'M', 'B', 'R', 'K', 'P', 'T')
+#define ARM_SOFTWARE_BREAKPOINT_FROM_LINK(a) CR(a, ARM_SOFTWARE_BREAKPOINT, Link, ARM_SOFTWARE_BREAKPOINT_SIGNATURE)
+
+LIST_ENTRY BreakpointList;
+
+/**
+ Insert Single Step in the SystemContext
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+AddSingleStep (
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ if (mSingleStepActive) {
+ // Currently don't support nesting
+ return;
+ }
+ mSingleStepActive = TRUE;
+
+ mSingleStepPC = SystemContext.SystemContextArm->PC;
+
+ mSingleStepDataSize = sizeof (UINT32);
+ mSingleStepData = (*(UINT32 *)mSingleStepPC);
+ *(UINT32 *)mSingleStepPC = GDB_ARM_BKPT;
+ if (*(UINT32 *)mSingleStepPC != GDB_ARM_BKPT) {
+ // For some reason our breakpoint did not take
+ mSingleStepActive = FALSE;
+ }
+
+ InvalidateInstructionCacheRange((VOID *)mSingleStepPC, mSingleStepDataSize);
+ //DEBUG((EFI_D_ERROR, "AddSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, mSingleStepData, *(UINT32 *)mSingleStepPC));
+}
+
+
+/**
+ Remove Single Step in the SystemContext
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+RemoveSingleStep (
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ if (!mSingleStepActive) {
+ return;
+ }
+
+ if (mSingleStepDataSize == sizeof (UINT16)) {
+ *(UINT16 *)mSingleStepPC = (UINT16)mSingleStepData;
+ } else {
+ //DEBUG((EFI_D_ERROR, "RemoveSingleStep at 0x%08x (was: 0x%08x is:0x%08x)\n", SystemContext.SystemContextArm->PC, *(UINT32 *)mSingleStepPC, mSingleStepData));
+ *(UINT32 *)mSingleStepPC = mSingleStepData;
+ }
+ InvalidateInstructionCacheRange((VOID *)mSingleStepPC, mSingleStepDataSize);
+ mSingleStepActive = FALSE;
+}
+
+
+
+/** ‘c [addr ]’
+ Continue. addr is Address to resume. If addr is omitted, resume at current
+ Address.
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+EFIAPI
+ContinueAtAddress (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ if (PacketData[1] != '\0') {
+ SystemContext.SystemContextArm->PC = AsciiStrHexToUintn(&PacketData[1]);
+ }
+}
+
+
+/** ‘s [addr ]’
+ Single step. addr is the Address at which to resume. If addr is omitted, resume
+ at same Address.
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+EFIAPI
+SingleStep (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ SendNotSupported();
+}
+
+UINTN
+GetBreakpointDataAddress (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN BreakpointNumber
+ )
+{
+ return 0;
+}
+
+UINTN
+GetBreakpointDetected (
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ return 0;
+}
+
+BREAK_TYPE
+GetBreakpointType (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN BreakpointNumber
+ )
+{
+ return NotSupported;
+}
+
+ARM_SOFTWARE_BREAKPOINT *
+SearchBreakpointList (
+ IN UINT32 Address
+ )
+{
+ LIST_ENTRY *Current;
+ ARM_SOFTWARE_BREAKPOINT *Breakpoint;
+
+ Current = GetFirstNode(&BreakpointList);
+ while (!IsNull(&BreakpointList, Current)) {
+ Breakpoint = ARM_SOFTWARE_BREAKPOINT_FROM_LINK(Current);
+
+ if (Address == Breakpoint->Address) {
+ return Breakpoint;
+ }
+
+ Current = GetNextNode(&BreakpointList, Current);
+ }
+
+ return NULL;
+}
+
+VOID
+SetBreakpoint (
+ IN UINT32 Address
+ )
+{
+ ARM_SOFTWARE_BREAKPOINT *Breakpoint;
+
+ Breakpoint = SearchBreakpointList(Address);
+
+ if (Breakpoint != NULL) {
+ return;
+ }
+
+ // create and fill breakpoint structure
+ Breakpoint = AllocatePool(sizeof(ARM_SOFTWARE_BREAKPOINT));
+
+ Breakpoint->Signature = ARM_SOFTWARE_BREAKPOINT_SIGNATURE;
+ Breakpoint->Address = Address;
+ Breakpoint->Instruction = *(UINT32 *)Address;
+
+ // Add it to the list
+ InsertTailList(&BreakpointList, &Breakpoint->Link);
+
+ // Insert the software breakpoint
+ *(UINT32 *)Address = GDB_ARM_BKPT;
+ InvalidateInstructionCacheRange((VOID *)Address, 4);
+
+ //DEBUG((EFI_D_ERROR, "SetBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, Breakpoint->Instruction, *(UINT32 *)Address));
+}
+
+VOID
+ClearBreakpoint (
+ IN UINT32 Address
+ )
+{
+ ARM_SOFTWARE_BREAKPOINT *Breakpoint;
+
+ Breakpoint = SearchBreakpointList(Address);
+
+ if (Breakpoint == NULL) {
+ return;
+ }
+
+ // Add it to the list
+ RemoveEntryList(&Breakpoint->Link);
+
+ // Restore the original instruction
+ *(UINT32 *)Address = Breakpoint->Instruction;
+ InvalidateInstructionCacheRange((VOID *)Address, 4);
+
+ //DEBUG((EFI_D_ERROR, "ClearBreakpoint at 0x%08x (was: 0x%08x is:0x%08x)\n", Address, GDB_ARM_BKPT, *(UINT32 *)Address));
+
+ FreePool(Breakpoint);
+}
+
+VOID
+EFIAPI
+InsertBreakPoint (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ UINTN Type;
+ UINTN Address;
+ UINTN Length;
+ UINTN ErrorCode;
+
+ ErrorCode = ParseBreakpointPacket(PacketData, &Type, &Address, &Length);
+ if (ErrorCode > 0) {
+ SendError ((UINT8)ErrorCode);
+ return;
+ }
+
+ switch (Type) {
+ case 0: //Software breakpoint
+ break;
+
+ default :
+ DEBUG((EFI_D_ERROR, "Insert breakpoint default: %x\n", Type));
+ SendError (GDB_EINVALIDBRKPOINTTYPE);
+ return;
+ }
+
+ SetBreakpoint(Address);
+
+ SendSuccess ();
+}
+
+VOID
+EFIAPI
+RemoveBreakPoint (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ UINTN Type;
+ UINTN Address;
+ UINTN Length;
+ UINTN ErrorCode;
+
+ //Parse breakpoint packet data
+ ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
+ if (ErrorCode > 0) {
+ SendError ((UINT8)ErrorCode);
+ return;
+ }
+
+ switch (Type) {
+ case 0: //Software breakpoint
+ break;
+
+ default:
+ SendError (GDB_EINVALIDBRKPOINTTYPE);
+ return;
+ }
+
+ ClearBreakpoint(Address);
+
+ SendSuccess ();
+}
+
+VOID
+InitializeProcessor (
+ VOID
+ )
+{
+ // Initialize breakpoint list
+ InitializeListHead(&BreakpointList);
+}
+
+BOOLEAN
+ValidateAddress (
+ IN VOID *Address
+ )
+{
+ if ((UINT32)Address < 0x80000000) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+BOOLEAN
+ValidateException (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT32 ExceptionAddress;
+ UINT32 Instruction;
+
+ // Is it a debugger SWI?
+ ExceptionAddress = SystemContext.SystemContextArm->PC -= 4;
+ Instruction = *(UINT32 *)ExceptionAddress;
+ if (Instruction != GDB_ARM_BKPT) {
+ return FALSE;
+ }
+
+ // Special for SWI-based exception handling. SWI sets up the context
+ // to return to the instruction following the SWI instruction - NOT what we want
+ // for a debugger!
+ SystemContext.SystemContextArm->PC = ExceptionAddress;
+
+ return TRUE;
+}
+
diff --git a/EmbeddedPkg/GdbStub/GdbStub.c b/EmbeddedPkg/GdbStub/GdbStub.c new file mode 100644 index 0000000000..b121e413f3 --- /dev/null +++ b/EmbeddedPkg/GdbStub/GdbStub.c @@ -0,0 +1,1264 @@ +/** @file + UEFI driver that implements a GDB stub + + Note: Any code in the path of the Serial IO output can not call DEBUG as will + will blow out the stack. Serial IO calls DEBUG, debug calls Serail IO, ... + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <GdbStubInternal.h> +#include <Protocol/DebugPort.h> + + +UINTN gMaxProcessorIndex = 0; + +// +// Buffers for basic gdb communication +// +CHAR8 gInBuffer[MAX_BUF_SIZE]; +CHAR8 gOutBuffer[MAX_BUF_SIZE]; + +// Assume gdb does a "qXfer:libraries:read::offset,length" when it connects so we can default +// this value to FALSE. Since gdb can reconnect its self a global default is not good enough +BOOLEAN gSymbolTableUpdate = FALSE; +EFI_EVENT gEvent; +VOID *gGdbSymbolEventHandlerRegistration = NULL; + +// +// Globals for returning XML from qXfer:libraries:read packet +// +UINTN gPacketqXferLibraryOffset = 0; +UINTN gEfiDebugImageTableEntry = 0; +EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL; +EFI_DEBUG_IMAGE_INFO *gDebugTable = NULL; +CHAR8 gXferLibraryBuffer[2000]; + +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexToStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + + +VOID +EFIAPI +GdbSymbolEventHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} + + +/** + The user Entry Point for Application. 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 +GdbStubEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + EFI_STATUS Status; + EFI_DEBUG_SUPPORT_PROTOCOL *DebugSupport; + UINTN HandleCount; + EFI_HANDLE *Handles; + UINTN Index; + UINTN Processor; + BOOLEAN IsaSupported; + + + Status = EfiGetSystemConfigurationTable (&gEfiDebugImageInfoTableGuid, (VOID **)&gDebugImageTableHeader); + if (EFI_ERROR (Status)) { + gDebugImageTableHeader = NULL; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDebugSupportProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Debug Support Protocol not found\n")); + + return Status; + } + + DebugSupport = NULL; + IsaSupported = FALSE; + do { + HandleCount--; + Status = gBS->HandleProtocol ( + Handles[HandleCount], + &gEfiDebugSupportProtocolGuid, + (VOID **) &DebugSupport + ); + if (!EFI_ERROR (Status)) { + if (CheckIsa (DebugSupport->Isa)) { + // We found what we are looking for so break out of the loop + IsaSupported = TRUE; + break; + } + } + } while (HandleCount > 0); + FreePool (Handles); + + if (!IsaSupported) { + DEBUG ((EFI_D_ERROR, "Debug Support Protocol does not support our ISA\n")); + + return EFI_NOT_FOUND; + } + + Status = DebugSupport->GetMaximumProcessorIndex (DebugSupport, &gMaxProcessorIndex); + ASSERT_EFI_ERROR (Status); + + // Make this an EFI_D_INFO after we get everything debugged. + DEBUG ((EFI_D_ERROR, "Debug Support Protocol ISA %x\n", DebugSupport->Isa)); + DEBUG ((EFI_D_ERROR, "Debug Support Protocol Processor Index %d\n", gMaxProcessorIndex)); + + // Call processor-specific init routine + InitializeProcessor(); + + for (Processor = 0; Processor <= gMaxProcessorIndex; Processor++) { + + for (Index = 0; Index < MaxEfiException (); Index++) { + Status = DebugSupport->RegisterExceptionCallback (DebugSupport, Processor, GdbExceptionHandler, gExceptionType[Index].Exception); + ASSERT_EFI_ERROR (Status); + } + // + // Current edk2 DebugPort is not interrupt context safe so we can not use it + // + Status = DebugSupport->RegisterPeriodicCallback (DebugSupport, Processor, GdbPeriodicCallBack); + ASSERT_EFI_ERROR (Status); + } + + // + // This even fires every time an image is added. This allows the stub to know when gdb needs + // to update the symbol table. + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + GdbSymbolEventHandler, + NULL, + &gEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for protocol notifactions on this event + // + Status = gBS->RegisterProtocolNotify ( + &gEfiLoadedImageProtocolGuid, + gEvent, + &gGdbSymbolEventHandlerRegistration + ); + ASSERT_EFI_ERROR (Status); + + + if (PcdGetBool (PcdGdbSerial)) { + GdbInitializeSerialConsole (); + } + + return EFI_SUCCESS; +} + + + +/** + Transfer length bytes of input buffer, starting at Address, to memory. + + @param length the number of the bytes to be transferred/written + @param *address the start address of the transferring/writing the memory + @param *new_data the new data to be written to memory + **/ + +VOID +TransferFromInBufToMem ( + IN UINTN Length, + IN unsigned char *Address, + IN CHAR8 *NewData + ) +{ + CHAR8 c1; + CHAR8 c2; + + while (Length-- > 0) { + c1 = (CHAR8)HexCharToInt (*NewData++); + c2 = (CHAR8)HexCharToInt (*NewData++); + + if ((c1 < 0) || (c2 < 0)) { + Print ((CHAR16 *)L"Bad message from write to memory..\n"); + SendError (GDB_EBADMEMDATA); + return; + } + *Address++ = (UINT8)((c1 << 4) + c2); + } + + SendSuccess(); +} + + +/** + Transfer Length bytes of memory starting at Address to an output buffer, OutBuffer. This function will finally send the buffer + as a packet. + + @param Length the number of the bytes to be transferred/read + @param *address pointer to the start address of the transferring/reading the memory + **/ + +VOID +TransferFromMemToOutBufAndSend ( + IN UINTN Length, + IN unsigned char *Address + ) +{ + // there are Length bytes and every byte is represented as 2 hex chars + CHAR8 OutBuffer[MAX_BUF_SIZE]; + CHAR8 *OutBufPtr; // pointer to the output buffer + CHAR8 Char; + + if (ValidateAddress(Address) == FALSE) { + SendError(14); + return; + } + + OutBufPtr = OutBuffer; + while (Length > 0) { + + Char = mHexToStr[*Address >> 4]; + if ((Char >= 'A') && (Char <= 'F')) { + Char = Char - 'A' + 'a'; + } + *OutBufPtr++ = Char; + + Char = mHexToStr[*Address & 0x0f]; + if ((Char >= 'A') && (Char <= 'F')) { + Char = Char - 'A' + 'a'; + } + *OutBufPtr++ = Char; + + Address++; + Length--; + } + + *OutBufPtr = '\0' ; // the end of the buffer + SendPacket (OutBuffer); +} + + + +/** + Send a GDB Remote Serial Protocol Packet + + $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', + the packet teminating character '#' and the two digit checksum. + + If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up + in an infinit loop. This is so if you unplug the debugger code just keeps running + + @param PacketData Payload data for the packet + + + @retval Number of bytes of packet data sent. + +**/ +UINTN +SendPacket ( + IN CHAR8 *PacketData + ) +{ + UINT8 CheckSum; + UINTN Timeout; + CHAR8 *Ptr; + CHAR8 TestChar; + UINTN Count; + + Timeout = PcdGet32 (PcdGdbMaxPacketRetryCount); + + Count = 0; + do { + + Ptr = PacketData; + + if (Timeout-- == 0) { + // Only try a finite number of times so we don't get stuck in the loop + return Count; + } + + // Packet prefix + GdbPutChar ('$'); + + for (CheckSum = 0, Count =0 ; *Ptr != '\0'; Ptr++, Count++) { + GdbPutChar (*Ptr); + CheckSum = CheckSum + *Ptr; + } + + // Packet terminating character and checksum + GdbPutChar ('#'); + GdbPutChar (mHexToStr[CheckSum >> 4]); + GdbPutChar (mHexToStr[CheckSum & 0x0F]); + + TestChar = GdbGetChar (); + } while (TestChar != '+'); + + return Count; +} + +/** + Receive a GDB Remote Serial Protocol Packet + + $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', + the packet teminating character '#' and the two digit checksum. + + If host re-starts sending a packet without ending the previous packet, only the last valid packet is proccessed. + (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.) + + If an ack '+' is not sent resend the packet + + @param PacketData Payload data for the packet + + @retval Number of bytes of packet data received. + +**/ +UINTN +ReceivePacket ( + OUT CHAR8 *PacketData, + IN UINTN PacketDataSize + ) +{ + UINT8 CheckSum; + UINTN Index; + CHAR8 Char; + CHAR8 SumString[3]; + CHAR8 TestChar; + + ZeroMem (PacketData, PacketDataSize); + + for (;;) { + // wait for the start of a packet + TestChar = GdbGetChar (); + while (TestChar != '$') { + TestChar = GdbGetChar (); + }; + + retry: + for (Index = 0, CheckSum = 0; Index < (PacketDataSize - 1); Index++) { + Char = GdbGetChar (); + if (Char == '$') { + goto retry; + } + if (Char == '#') { + break; + } + + PacketData[Index] = Char; + CheckSum = CheckSum + Char; + } + PacketData[Index] = '\0'; + + if (Index == PacketDataSize) { + continue; + } + + SumString[0] = GdbGetChar (); + SumString[1] = GdbGetChar (); + SumString[2] = '\0'; + + if (AsciiStrHexToUintn (SumString) == CheckSum) { + // Ack: Success + GdbPutChar ('+'); + + // Null terminate the callers string + PacketData[Index] = '\0'; + return Index; + } else { + // Ack: Failure + GdbPutChar ('-'); + } + } + + //return 0; +} + + +/** + Empties the given buffer + @param Buf pointer to the first element in buffer to be emptied + **/ +VOID +EmptyBuffer ( + IN CHAR8 *Buf + ) +{ + *Buf = '\0'; +} + + +/** + Converts an 8-bit Hex Char into a INTN. + + @param Char the hex character to be converted into UINTN + @retval a INTN, from 0 to 15, that corressponds to Char + -1 if Char is not a hex character + **/ +INTN +HexCharToInt ( + IN CHAR8 Char + ) +{ + if ((Char >= 'A') && (Char <= 'F')) { + return Char - 'A' + 10; + } else if ((Char >= 'a') && (Char <= 'f')) { + return Char - 'a' + 10; + } else if ((Char >= '0') && (Char <= '9')) { + return Char - '0'; + } else { // if not a hex value, return a negative value + return -1; + } +} + + // 'E' + the biggest error number is 255, so its 2 hex digits + buffer end +CHAR8 *gError = "E__"; + +/** 'E NN' + Send an error with the given error number after converting to hex. + The error number is put into the buffer in hex. '255' is the biggest errno we can send. + ex: 162 will be sent as A2. + + @param errno the error number that will be sent + **/ +VOID +EFIAPI +SendError ( + IN UINT8 ErrorNum + ) +{ + // + // Replace _, or old data, with current errno + // + gError[1] = mHexToStr [ErrorNum >> 4]; + gError[2] = mHexToStr [ErrorNum & 0x0f]; + + SendPacket (gError); // send buffer +} + + + +/** + Send 'OK' when the function is done executing successfully. + **/ +VOID +EFIAPI +SendSuccess ( + VOID + ) +{ + SendPacket ("OK"); // send buffer +} + + +/** + Send empty packet to specify that particular command/functionality is not supported. + **/ +VOID +EFIAPI +SendNotSupported ( + VOID + ) +{ + SendPacket (""); +} + + + +/** + Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints + + @param SystemContext Register content at time of the exception + @param GdbExceptionType GDB exception type + **/ +VOID +GdbSendTSignal ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINT8 GdbExceptionType + ) +{ + CHAR8 TSignalBuffer[128]; + CHAR8 *TSignalPtr; + UINTN BreakpointDetected; + BREAK_TYPE BreakType; + UINTN DataAddress; + CHAR8 *WatchStrPtr = NULL; + UINTN RegSize; + + TSignalPtr = &TSignalBuffer[0]; + + //Construct TSignal packet + *TSignalPtr++ = 'T'; + + // + // replace _, or previous value, with Exception type + // + *TSignalPtr++ = mHexToStr [GdbExceptionType >> 4]; + *TSignalPtr++ = mHexToStr [GdbExceptionType & 0x0f]; + + if (GdbExceptionType == GDB_SIGTRAP) { + if (gSymbolTableUpdate) { + // + // We can only send back on reason code. So if the flag is set it means the breakpoint is from our event handler + // + WatchStrPtr = "library:;"; + while (*WatchStrPtr != '\0') { + *TSignalPtr++ = *WatchStrPtr++; + } + gSymbolTableUpdate = FALSE; + } else { + + + // + // possible n:r pairs + // + + //Retrieve the breakpoint number + BreakpointDetected = GetBreakpointDetected (SystemContext); + + //Figure out if the exception is happend due to watch, rwatch or awatch. + BreakType = GetBreakpointType (SystemContext, BreakpointDetected); + + //INFO: rwatch is not supported due to the way IA32 debug registers work + if ((BreakType == DataWrite) || (BreakType == DataRead) || (BreakType == DataReadWrite)) { + + //Construct n:r pair + DataAddress = GetBreakpointDataAddress (SystemContext, BreakpointDetected); + + //Assign appropriate buffer to print particular watchpoint type + if (BreakType == DataWrite) { + WatchStrPtr = "watch"; + } else if (BreakType == DataRead) { + WatchStrPtr = "rwatch"; + } else if (BreakType == DataReadWrite) { + WatchStrPtr = "awatch"; + } + + while (*WatchStrPtr != '\0') { + *TSignalPtr++ = *WatchStrPtr++; + } + + *TSignalPtr++ = ':'; + + //Set up series of bytes in big-endian byte order. "awatch" won't work with little-endian byte order. + RegSize = REG_SIZE; + while (RegSize > 0) { + RegSize = RegSize-4; + *TSignalPtr++ = mHexToStr[(UINT8)(DataAddress >> RegSize) & 0xf]; + } + + //Always end n:r pair with ';' + *TSignalPtr++ = ';'; + } + } + } + + *TSignalPtr = '\0'; + + SendPacket (TSignalBuffer); +} + + +/** + Translates the EFI mapping to GDB mapping + + @param EFIExceptionType EFI Exception that is being processed + @retval UINTN that corresponds to EFIExceptionType's GDB exception type number + **/ +UINT8 +ConvertEFItoGDBtype ( + IN EFI_EXCEPTION_TYPE EFIExceptionType + ) +{ + UINTN i; + + for (i=0; i < MaxEfiException() ; i++) { + if (gExceptionType[i].Exception == EFIExceptionType) { + return gExceptionType[i].SignalNo; + } + } + return GDB_SIGTRAP; // this is a GDB trap +} + + +/** "m addr,length" + Find the Length of the area to read and the start addres. Finally, pass them to + another function, TransferFromMemToOutBufAndSend, that will read from that memory space and + send it as a packet. + **/ + +VOID +EFIAPI +ReadFromMemory ( + CHAR8 *PacketData + ) +{ + UINTN Address; + UINTN Length; + CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the address in hex chars + CHAR8 *AddrBufPtr; // pointer to the address buffer + CHAR8 *InBufPtr; /// pointer to the input buffer + + AddrBufPtr = AddressBuffer; + InBufPtr = &PacketData[1]; + while (*InBufPtr != ',') { + *AddrBufPtr++ = *InBufPtr++; + } + *AddrBufPtr = '\0'; + + InBufPtr++; // this skips ',' in the buffer + + /* Error checking */ + if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) { + Print((CHAR16 *)L"Address is too long\n"); + SendError (GDB_EBADMEMADDRBUFSIZE); + return; + } + + // 2 = 'm' + ',' + if (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - 2 >= MAX_LENGTH_SIZE) { + Print((CHAR16 *)L"Length is too long\n"); + SendError (GDB_EBADMEMLENGTH); + return; + } + + Address = AsciiStrHexToUintn (AddressBuffer); + Length = AsciiStrHexToUintn (InBufPtr); + + TransferFromMemToOutBufAndSend (Length, (unsigned char *)Address); +} + + +/** "M addr,length :XX..." + Find the Length of the area in bytes to write and the start addres. Finally, pass them to + another function, TransferFromInBufToMem, that will write to that memory space the info in + the input buffer. + **/ +VOID +EFIAPI +WriteToMemory ( + IN CHAR8 *PacketData + ) +{ + UINTN Address; + UINTN Length; + UINTN MessageLength; + CHAR8 AddressBuffer[MAX_ADDR_SIZE]; // the buffer that will hold the Address in hex chars + CHAR8 LengthBuffer[MAX_LENGTH_SIZE]; // the buffer that will hold the Length in hex chars + CHAR8 *AddrBufPtr; // pointer to the Address buffer + CHAR8 *LengthBufPtr; // pointer to the Length buffer + CHAR8 *InBufPtr; /// pointer to the input buffer + + AddrBufPtr = AddressBuffer; + LengthBufPtr = LengthBuffer; + InBufPtr = &PacketData[1]; + + while (*InBufPtr != ',') { + *AddrBufPtr++ = *InBufPtr++; + } + *AddrBufPtr = '\0'; + + InBufPtr++; // this skips ',' in the buffer + + while (*InBufPtr != ':') { + *LengthBufPtr++ = *InBufPtr++; + } + *LengthBufPtr = '\0'; + + InBufPtr++; // this skips ':' in the buffer + + Address = AsciiStrHexToUintn (AddressBuffer); + Length = AsciiStrHexToUintn (LengthBuffer); + + /* Error checking */ + + //Check if Address is not too long. + if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) { + Print ((CHAR16 *)L"Address too long..\n"); + SendError (GDB_EBADMEMADDRBUFSIZE); + return; + } + + //Check if message length is not too long + if (AsciiStrLen(LengthBuffer) >= MAX_LENGTH_SIZE) { + Print ((CHAR16 *)L"Length too long..\n"); + SendError (GDB_EBADMEMLENGBUFSIZE); + return; + } + + // Check if Message is not too long/short. + // 3 = 'M' + ',' + ':' + MessageLength = (AsciiStrLen(PacketData) - AsciiStrLen(AddressBuffer) - AsciiStrLen(LengthBuffer) - 3); + if (MessageLength != (2*Length)) { + //Message too long/short. New data is not the right size. + SendError (GDB_EBADMEMDATASIZE); + return; + } + TransferFromInBufToMem (Length, (unsigned char *)Address, InBufPtr); +} + +/** + Parses breakpoint packet data and captures Breakpoint type, Address and length. + In case of an error, function returns particular error code. Returning 0 meaning + no error. + + @param PacketData Pointer to the payload data for the packet. + @param Type Breakpoint type + @param Address Breakpoint address + @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte) + + @retval 1 Success + @retval {other} Particular error code + +**/ +UINTN +ParseBreakpointPacket ( + IN CHAR8 *PacketData, + OUT UINTN *Type, + OUT UINTN *Address, + OUT UINTN *Length + ) +{ + CHAR8 AddressBuffer[MAX_ADDR_SIZE]; + CHAR8 *AddressBufferPtr; + CHAR8 *PacketDataPtr; + + PacketDataPtr = &PacketData[1]; + AddressBufferPtr = AddressBuffer; + + *Type = AsciiStrHexToUintn (PacketDataPtr); + + //Breakpoint/watchpoint type should be between 0 to 4 + if (*Type > 4) { + Print ((CHAR16 *)L"Type is invalid\n"); + return 22; //EINVAL: Invalid argument. + } + + //Skip ',' in the buffer. + while (*PacketDataPtr++ != ','); + + //Parse Address information + while (*PacketDataPtr != ',') { + *AddressBufferPtr++ = *PacketDataPtr++; + } + *AddressBufferPtr = '\0'; + + //Check if Address is not too long. + if (AsciiStrLen(AddressBuffer) >= MAX_ADDR_SIZE) { + Print ((CHAR16 *)L"Address too long..\n"); + return 40; //EMSGSIZE: Message size too long. + } + + *Address = AsciiStrHexToUintn (AddressBuffer); + + PacketDataPtr++; //This skips , in the buffer + + //Parse Length information + *Length = AsciiStrHexToUintn (PacketDataPtr); + + //Length should be 1, 2 or 4 bytes + if (*Length > 4) { + Print ((CHAR16 *)L"Length is invalid\n"); + return 22; //EINVAL: Invalid argument + } + + return 0; //0 = No error +} + +UINTN +gXferObjectReadResponse ( + IN CHAR8 Type, + IN CHAR8 *Str + ) +{ + CHAR8 *OutBufPtr; // pointer to the output buffer + CHAR8 Char; + UINTN Count; + + // responce starts with 'm' or 'l' if it is the end + OutBufPtr = gOutBuffer; + *OutBufPtr++ = Type; + Count = 1; + + // Binary data encoding + OutBufPtr = gOutBuffer; + while (*Str != '\0') { + Char = *Str++; + if ((Char == 0x7d) || (Char == 0x23) || (Char == 0x24) || (Char == 0x2a)) { + // escape character + *OutBufPtr++ = 0x7d; + + Char ^= 0x20; + } + *OutBufPtr++ = Char; + Count++; + } + + *OutBufPtr = '\0' ; // the end of the buffer + SendPacket (gOutBuffer); + + return Count; +} + + +/** + Note: This should be a library function. In the Apple case you have to add + the size of the PE/COFF header into the starting address to make things work + right as there is no way to pad the Mach-O for the size of the PE/COFF header. + + + Returns a pointer to the PDB file name for a PE/COFF image that has been + loaded into system memory with the PE/COFF Loader Library functions. + + Returns the PDB file name for the PE/COFF image specified by Pe32Data. If + the PE/COFF image specified by Pe32Data is not a valid, then NULL is + returned. If the PE/COFF image specified by Pe32Data does not contain a + debug directory entry, then NULL is returned. If the debug directory entry + in the PE/COFF image specified by Pe32Data does not contain a PDB file name, + then NULL is returned. + If Pe32Data is NULL, then ASSERT(). + + @param Pe32Data Pointer to the PE/COFF image that is loaded in system + memory. + @param DebugBase Address that the debugger would use as the base of the image + + @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL + if it cannot be retrieved. DebugBase is only valid if PDB file name is + valid. + +**/ +VOID * +EFIAPI +PeCoffLoaderGetDebuggerInfo ( + IN VOID *Pe32Data, + OUT VOID **DebugBase + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN DirCount; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + UINT32 NumberOfRvaAndSizes; + UINT16 Magic; + UINTN SizeOfHeaders; + + ASSERT (Pe32Data != NULL); + + TEImageAdjust = 0; + DirectoryEntry = NULL; + DebugEntry = NULL; + NumberOfRvaAndSizes = 0; + SizeOfHeaders = 0; + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize; + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te + + Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + + TEImageAdjust); + } + SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize; + + // __APPLE__ check this math... + *DebugBase = ((CHAR8 *)Pe32Data) - TEImageAdjust; + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + + *DebugBase = Pe32Data; + + + // + // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic. + // It is due to backward-compatibility, for some system might + // generate PE32+ image with PE32 Magic. + // + switch (Hdr.Pe32->FileHeader.Machine) { + case EFI_IMAGE_MACHINE_IA32: + // + // Assume PE32 image with IA32 Machine field. + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + break; + case EFI_IMAGE_MACHINE_X64: + case EFI_IMAGE_MACHINE_IA64: + // + // Assume PE32+ image with X64 or IPF Machine field + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + default: + // + // For unknow Machine field, use Magic in optional Header + // + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // Use PE32 offset get Debug Directory Entry + // + SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders; + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress); + } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + // + // Use PE32+ offset get Debug Directory Entry + // + SizeOfHeaders = Hdr.Pe32Plus->OptionalHeader.SizeOfHeaders; + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress); + } + + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = NULL; + DebugEntry = NULL; + } + } else { + return NULL; + } + + if (DebugEntry == NULL || DirectoryEntry == NULL) { + return NULL; + } + + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) { + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + if (DebugEntry->SizeOfData > 0) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust); + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)); + case CODEVIEW_SIGNATURE_RSDS: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY)); + case CODEVIEW_SIGNATURE_MTOC: + *DebugBase = (VOID *)(UINTN)((UINTN)DebugBase + SizeOfHeaders); + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY)); + default: + break; + } + } + } + } + + (void)SizeOfHeaders; + return NULL; +} + + + +/** + Process "qXfer:object:read:annex:offset,length" request. + + Returns an XML document that contains loaded libraries. In our case it is + infomration in the EFI Debug Inmage Table converted into an XML document. + + GDB will call with an arbitrary length (it can't know the real length and + will reply with chunks of XML that are easy for us to deal with. Gdb will + keep calling until we say we are done. XML doc looks like: + + <library-list> + <library name="/a/a/c/d.dSYM"><segment address="0x10000000"/></library> + <library name="/a/m/e/e.pdb"><segment address="0x20000000"/></library> + <library name="/a/l/f/f.dll"><segment address="0x30000000"/></library> + </library-list> + + Since we can not allocate memory in interupt context this module has + assumptions about how it will get called: + 1) Length will generally be max remote packet size (big enough) + 2) First Offset of an XML document read needs to be 0 + 3) This code will return back small chunks of the XML document on every read. + Each subseqent call will ask for the next availble part of the document. + + Note: The only variable size element in the XML is: + " <library name=\"%s\"><segment address=\"%p\"/></library>\n" and it is + based on the file path and name of the symbol file. If the symbol file name + is bigger than the max gdb remote packet size we could update this code + to respond back in chunks. + + @param Offset offset into special data area + @param Length number of bytes to read starting at Offset + + **/ +VOID +QxferLibrary ( + IN UINTN Offset, + IN UINTN Length + ) +{ + VOID *LoadAddress; + CHAR8 *Pdb; + UINTN Size; + + if (Offset != gPacketqXferLibraryOffset) { + SendError (GDB_EINVALIDARG); + Print (L"\nqXferLibrary (%d, %d) != %d\n", Offset, Length, gPacketqXferLibraryOffset); + + // Force a retry from the beginning + gPacketqXferLibraryOffset = 0; + return; + } + + if (Offset == 0) { + gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', "<library-list>\n"); + + // The owner of the table may have had to ralloc it so grab a fresh copy every time + // we assume qXferLibrary will get called over and over again until the entire XML table is + // returned in a tight loop. Since we are in the debugger the table should not get updated + gDebugTable = gDebugImageTableHeader->EfiDebugImageInfoTable; + gEfiDebugImageTableEntry = 0; + return; + } + + if (gDebugTable != NULL) { + for (; gEfiDebugImageTableEntry < gDebugImageTableHeader->TableSize; gEfiDebugImageTableEntry++, gDebugTable++) { + if (gDebugTable->NormalImage != NULL) { + if ((gDebugTable->NormalImage->ImageInfoType == EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL) && + (gDebugTable->NormalImage->LoadedImageProtocolInstance != NULL)) { + Pdb = PeCoffLoaderGetDebuggerInfo ( + gDebugTable->NormalImage->LoadedImageProtocolInstance->ImageBase, + &LoadAddress + ); + if (Pdb != NULL) { + Size = AsciiSPrint ( + gXferLibraryBuffer, + sizeof (gXferLibraryBuffer), + " <library name=\"%a\"><segment address=\"0x%p\"/></library>\n", + Pdb, + LoadAddress + ); + if ((Size != 0) && (Size != (sizeof (gXferLibraryBuffer) - 1))) { + gPacketqXferLibraryOffset += gXferObjectReadResponse ('m', gXferLibraryBuffer); + + // Update loop variables so we are in the right place when we get back + gEfiDebugImageTableEntry++; + gDebugTable++; + return; + } else { + // We could handle <library> entires larger than sizeof (gXferLibraryBuffer) here if + // needed by breaking up into N packets + // "<library name=\"%s + // the rest of the string (as many packets as required + // \"><segment address=\"%d\"/></library> (fixed size) + // + // But right now we just skip any entry that is too big + } + } + } + } + } + } + + + gXferObjectReadResponse ('l', "</library-list>\n"); + gPacketqXferLibraryOffset = 0; + return; +} + + +/** + Exception Hanldler for GDB. It will be called for all exceptions + registered via the gExceptionType[] array. + + @param ExceptionType Exception that is being processed + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +GdbExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINT8 GdbExceptionType; + CHAR8 *Ptr; + + + if (ValidateException(ExceptionType, SystemContext) == FALSE) { + return; + } + + RemoveSingleStep (SystemContext); + + GdbExceptionType = ConvertEFItoGDBtype (ExceptionType); + GdbSendTSignal (SystemContext, GdbExceptionType); + + for( ; ; ) { + ReceivePacket (gInBuffer, MAX_BUF_SIZE); + + switch (gInBuffer[0]) { + case '?': + GdbSendTSignal (SystemContext, GdbExceptionType); + break; + + case 'c': + ContinueAtAddress (SystemContext, gInBuffer); + return; + + case 'g': + ReadGeneralRegisters (SystemContext); + break; + + case 'G': + WriteGeneralRegisters (SystemContext, gInBuffer); + break; + + case 'H': + //Return "OK" packet since we don't have more than one thread. + SendSuccess (); + break; + + case 'm': + ReadFromMemory (gInBuffer); + break; + + case 'M': + WriteToMemory (gInBuffer); + break; + + case 'P': + WriteNthRegister (SystemContext, gInBuffer); + break; + + // + // Still debugging this code. Not used in Darwin + // + case 'q': + // General Query Packets + if (AsciiStrnCmp (gInBuffer, "qSupported", 10) == 0) { + // return what we currently support, we don't parse what gdb suports + AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "qXfer:libraries:read+;PacketSize=%d", MAX_BUF_SIZE); + SendPacket (gOutBuffer); + } else if (AsciiStrnCmp (gInBuffer, "qXfer:libraries:read::", 22) == 0) { + // ‘qXfer:libraries:read::offset,length + // gInBuffer[22] is offset string, ++Ptr is length string’ + for (Ptr = &gInBuffer[22]; *Ptr != ','; Ptr++); + + // Not sure if multi-radix support is required. Currently only support decimal + QxferLibrary (AsciiStrHexToUintn (&gInBuffer[22]), AsciiStrHexToUintn (++Ptr)); + } if (AsciiStrnCmp (gInBuffer, "qOffsets", 10) == 0) { + AsciiSPrint (gOutBuffer, MAX_BUF_SIZE, "Text=1000;Data=f000;Bss=f000"); + SendPacket (gOutBuffer); + } else { + //Send empty packet + SendNotSupported (); + } + break; + + case 's': + SingleStep (SystemContext, gInBuffer); + return; + + case 'z': + RemoveBreakPoint (SystemContext, gInBuffer); + break; + + case 'Z': + InsertBreakPoint (SystemContext, gInBuffer); + break; + + default: + //Send empty packet + SendNotSupported (); + break; + } + } +} + + +/** + Periodic callback for GDB. This function is used to catch a ctrl-c or other + break in type command from GDB. + + @param SystemContext Register content at time of the call + **/ +VOID +EFIAPI +GdbPeriodicCallBack ( + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + // + // gCtrlCBreakFlag may have been set from a previous F response package + // and we set the global as we need to process it at a point where we + // can update the system context. If we are in the middle of processing + // a F Packet it is not safe to read the GDB serial stream so we need + // to skip it on this check + // + if (!gCtrlCBreakFlag && !gProcessingFPacket) { + // + // Ctrl-C was not pending so grab any pending characters and see if they + // are a Ctrl-c (0x03). If so set the Ctrl-C global. + // + while (TRUE) { + if (!GdbIsCharAvailable ()) { + // + // No characters are pending so exit the loop + // + break; + } + + if (GdbGetChar () == 0x03) { + gCtrlCBreakFlag = TRUE; + // + // We have a ctrl-c so exit the loop + // + break; + } + } + } + + if (gCtrlCBreakFlag) { + // + // Update the context to force a single step trap when we exit the GDB + // stub. This will trasfer control to GdbExceptionHandler () and let + // us break into the program. We don't want to break into the GDB stub. + // + AddSingleStep (SystemContext); + gCtrlCBreakFlag = FALSE; + } +} diff --git a/EmbeddedPkg/GdbStub/GdbStub.inf b/EmbeddedPkg/GdbStub/GdbStub.inf new file mode 100644 index 0000000000..2b54f0abef --- /dev/null +++ b/EmbeddedPkg/GdbStub/GdbStub.inf @@ -0,0 +1,78 @@ +#%HEADER%
+#/** @file
+# UEFI GDB stub
+#
+# This is a shell application that will display Hello World.
+# Copyright (c) 2008, Apple, Inc.
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = GdbStub
+ FILE_GUID = 1F2CCB4F-D817-404E-98E7-80E4851FB33E
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = GdbStubEntry
+
+[Sources.common]
+ GdbStub.c
+ SerialIo.c
+
+[Sources.ARM]
+ Arm/Processor.c
+
+[Sources.IA32]
+ Ia32/Processor.c
+
+[Sources.X64]
+ X64/Processor.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UefiLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ DevicePathLib
+ PcdLib
+ GdbSerialLib
+ PrintLib
+ CacheMaintenanceLib
+
+
+[Protocols]
+ gEfiDebugSupportProtocolGuid
+ gEfiDebugPortProtocolGuid
+ gEfiSerialIoProtocolGuid
+
+[Guids]
+ gEfiDebugImageInfoTableGuid
+
+[FeaturePcd.common]
+ gEmbeddedTokenSpaceGuid.PcdGdbSerial
+
+[FixedPcd.common]
+ gEmbeddedTokenSpaceGuid.PcdGdbMaxPacketRetryCount
diff --git a/EmbeddedPkg/GdbStub/GdbStubInternal.h b/EmbeddedPkg/GdbStub/GdbStubInternal.h new file mode 100644 index 0000000000..20231cff82 --- /dev/null +++ b/EmbeddedPkg/GdbStub/GdbStubInternal.h @@ -0,0 +1,746 @@ +/** @file + Private include file for GDB stub + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __GDB_STUB_INTERNAL__ +#define __GDB_STUB_INTERNAL__ + +#include <Uefi.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DebugLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/PcdLib.h> +#include <Library/GdbSerialLib.h> +#include <Library/PrintLib.h> + +#include <Protocol/DebugSupport.h> +#include <Protocol/SerialIo.h> +#include <Protocol/LoadedImage.h> +#include <Protocol/LoadedImage.h> +#include <Guid/DebugImageInfoTable.h> +#include <IndustryStandard/PeImage.h> + +extern CONST CHAR8 mHexToStr[]; + +// maximum size of input and output buffers +// This value came from the show remote command of the gdb we tested against +#define MAX_BUF_SIZE 2000 + +// maximum size of address buffer +#define MAX_ADDR_SIZE 32 + +// maximum size of register number buffer +#define MAX_REG_NUM_BUF_SIZE 32 + +// maximum size of length buffer +#define MAX_LENGTH_SIZE 32 + +// maximum size of T signal members +#define MAX_T_SIGNAL_SIZE 64 + +// the mask used to clear all the cache +#define TF_BIT 0x00000100 + + +// +// GDB Signal definitions - generic names for interrupts +// +#define GDB_SIGILL 4 // Illegal instruction +#define GDB_SIGTRAP 5 // Trace Trap (Breakpoint and SingleStep) +#define GDB_SIGEMT 7 // Emulator Trap +#define GDB_SIGFPE 8 // Floating point exception +#define GDB_SIGSEGV 11 // Setgment violation, page fault + + +// +// GDB File I/O Error values, zero means no error +// Includes all general GDB Unix like error values +// +#define GDB_EBADMEMADDRBUFSIZE 11 // the buffer that stores memory Address to be read from/written to is not the right size +#define GDB_EBADMEMLENGBUFSIZE 12 // the buffer that stores Length is not the right size +#define GDB_EBADMEMLENGTH 13 // Length, the given number of bytes to read or write, is not the right size +#define GDB_EBADMEMDATA 14 // one of the bytes or nibbles of the memory is leess than 0 +#define GDB_EBADMEMDATASIZE 15 // the memory data, 'XX..', is too short or too long +#define GDB_EBADBUFSIZE 21 // the buffer created is not the correct size +#define GDB_EINVALIDARG 31 // argument is invalid +#define GDB_ENOSPACE 41 // +#define GDB_EINVALIDBRKPOINTTYPE 51 // the breakpoint type is not recognized +#define GDB_EINVALIDREGNUM 61 // given register number is not valid: either <0 or >=Number of Registers +#define GDB_EUNKNOWN 255 // unknown + + +// +// These devices are open by GDB so we can just read and write to them +// +#define GDB_STDIN 0x00 +#define GDB_STDOUT 0x01 +#define GDB_STDERR 0x02 + +// +//Define Register size for different architectures +// +#if defined (MDE_CPU_IA32) +#define REG_SIZE 32 +#elif defined (MDE_CPU_X64) +#define REG_SIZE 64 +#elif defined (MDE_CPU_ARM) +#define REG_SIZE 32 +#endif + +#define GDB_SERIAL_DEV_SIGNATURE SIGNATURE_32 ('g', 'd', 'b', 's') + +typedef struct { + VENDOR_DEVICE_PATH VendorDevice; + UINT32 Index; // Suport more than one + EFI_DEVICE_PATH_PROTOCOL End; +} GDB_SERIAL_DEVICE_PATH; + +// +// Name: SERIAL_DEV +// Purpose: To provide device specific information +// Fields: +// Signature UINTN: The identity of the serial device +// SerialIo SERIAL_IO_PROTOCOL: Serial I/O protocol interface +// SerialMode SERIAL_IO_MODE: +// DevicePath EFI_DEVICE_PATH_PROTOCOL *: Device path of the serial device +// +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_SERIAL_IO_PROTOCOL SerialIo; + EFI_SERIAL_IO_MODE SerialMode; + GDB_SERIAL_DEVICE_PATH DevicePath; + INTN InFileDescriptor; + INTN OutFileDescriptor; +} GDB_SERIAL_DEV; + + +#define GDB_SERIAL_DEV_FROM_THIS(a) CR (a, GDB_SERIAL_DEV, SerialIo, GDB_SERIAL_DEV_SIGNATURE) + + +typedef struct { + EFI_EXCEPTION_TYPE Exception; + UINT8 SignalNo; +} EFI_EXCEPTION_TYPE_ENTRY; + + +#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) + +// +// Byte packed structure for DR6 +// 32-bits on IA-32 +// 64-bits on X64. The upper 32-bits on X64 are reserved +// +typedef union { + struct { + UINT32 B0:1; // Breakpoint condition detected + UINT32 B1:1; // Breakpoint condition detected + UINT32 B2:1; // Breakpoint condition detected + UINT32 B3:1; // Breakpoint condition detected + UINT32 Reserved_1:9; // Reserved + UINT32 BD:1; // Debug register access detected + UINT32 BS:1; // Single step + UINT32 BT:1; // Task switch + UINT32 Reserved_2:16; // Reserved + } Bits; + UINTN UintN; +} IA32_DR6; + +// +// Byte packed structure for DR7 +// 32-bits on IA-32 +// 64-bits on X64. The upper 32-bits on X64 are reserved +// +typedef union { + struct { + UINT32 L0:1; // Local breakpoint enable + UINT32 G0:1; // Global breakpoint enable + UINT32 L1:1; // Local breakpoint enable + UINT32 G1:1; // Global breakpoint enable + UINT32 L2:1; // Local breakpoint enable + UINT32 G2:1; // Global breakpoint enable + UINT32 L3:1; // Local breakpoint enable + UINT32 G3:1; // Global breakpoint enable + UINT32 LE:1; // Local exact breakpoint enable + UINT32 GE:1; // Global exact breakpoint enable + UINT32 Reserved_1:3; // Reserved + UINT32 GD:1; // Global detect enable + UINT32 Reserved_2:2; // Reserved + UINT32 RW0:2; // Read/Write field + UINT32 LEN0:2; // Length field + UINT32 RW1:2; // Read/Write field + UINT32 LEN1:2; // Length field + UINT32 RW2:2; // Read/Write field + UINT32 LEN2:2; // Length field + UINT32 RW3:2; // Read/Write field + UINT32 LEN3:2; // Length field + } Bits; + UINTN UintN; +} IA32_DR7; + +#endif /* if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) */ + +typedef enum { + InstructionExecution, //Hardware breakpoint + DataWrite, //watch + DataRead, //rwatch + DataReadWrite, //awatch + SoftwareBreakpoint, //Software breakpoint + NotSupported +} BREAK_TYPE; + +// +// Array of exception types that need to be hooked by the debugger +// +extern EFI_EXCEPTION_TYPE_ENTRY gExceptionType[]; + +// +// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c +// here we need to wait for the periodic callback to do this. +// +extern BOOLEAN gCtrlCBreakFlag; + +// +// If the periodic callback is called while we are processing an F packet we need +// to let the callback know to not read from the serail stream as it could steal +// characters from the F reponse packet +// +extern BOOLEAN gProcessingFPacket; + + +// The offsets of registers SystemContext. +// The fields in the array are in the gdb ordering. +// +extern UINTN gRegisterOffsets[]; + +/** + Return the number of entries in the gExceptionType[] + + @retval UINTN, the number of entries in the gExceptionType[] array. + **/ +UINTN +MaxEfiException ( + VOID + ); + + +/** + Return the number of entries in the gRegisters[] + + @retval UINTN, the number of entries (registers) in the gRegisters[] array. + **/ +UINTN +MaxRegisterCount ( + VOID + ); + + +/** + Check to see if the ISA is supported. + ISA = Instruction Set Architecture + + @retval TRUE if Isa is supported, + FALSE otherwise. + **/ +BOOLEAN +CheckIsa ( + IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa + ); + + +/** + Send the T signal with the given exception type (in gdb order) and possibly with n:r pairs related to the watchpoints + + @param SystemContext Register content at time of the exception + @param GdbExceptionType GDB exception type + **/ + +VOID +GdbSendTSignal ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINT8 GdbExceptionType + ); + + +/** + Translates the EFI mapping to GDB mapping + + @param EFIExceptionType EFI Exception that is being processed + @retval UINTN that corresponds to EFIExceptionType's GDB exception type number + **/ +UINT8 +ConvertEFItoGDBtype ( + IN EFI_EXCEPTION_TYPE EFIExceptionType + ); + + +/** + Empties the given buffer + @param *Buf pointer to the first element in buffer to be emptied + **/ +VOID +EmptyBuffer ( + IN CHAR8 *Buf + ); + + +/** + Converts an 8-bit Hex Char into a INTN. + + @param Char - the hex character to be converted into UINTN + @retval a INTN, from 0 to 15, that corressponds to Char + -1 if Char is not a hex character + **/ +INTN +HexCharToInt ( + IN CHAR8 Char + ); + + +/** 'E NN' + Send an error with the given error number after converting to hex. + The error number is put into the buffer in hex. '255' is the biggest errno we can send. + ex: 162 will be sent as A2. + + @param errno the error number that will be sent + **/ +VOID +EFIAPI +SendError ( + IN UINT8 ErrorNum + ); + + +/** + Send 'OK' when the function is done executing successfully. + **/ +VOID +SendSuccess ( + VOID + ); + + +/** + Send empty packet to specify that particular command/functionality is not supported. + **/ +VOID +SendNotSupported ( + VOID + ); + +/** ‘p n’ + Reads the n-th register's value into an output buffer and sends it as a packet + @param SystemContext Register content at time of the exception + @param InBuffer This is the input buffer received from gdb server + **/ +VOID +ReadNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ); + + +/** ‘g’ + Reads the general registers into an output buffer and sends it as a packet + @param SystemContext Register content at time of the exception + **/ +VOID +ReadGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext + ); + + +/** ‘P n...=r...’ + Writes the new value of n-th register received into the input buffer to the n-th register + @param SystemContext Register content at time of the exception + @param InBuffer This is the input buffer received from gdb server + **/ +VOID +WriteNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ); + + +/** ‘G XX...’ + Writes the new values received into the input buffer to the general registers + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ + +VOID +WriteGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ); + + +/** ‘m addr,length ’ + Find the Length of the area to read and the start addres. Finally, pass them to + another function, TransferFromMemToOutBufAndSend, that will read from that memory space and + send it as a packet. + + @param *PacketData Pointer to Payload data for the packet + **/ +VOID +ReadFromMemory ( + IN CHAR8 *PacketData + ); + + +/** ‘M addr,length :XX...’ + Find the Length of the area in bytes to write and the start addres. Finally, pass them to + another function, TransferFromInBufToMem, that will write to that memory space the info in + the input buffer. + + @param PacketData Pointer to Payload data for the packet + **/ +VOID +WriteToMemory ( + IN CHAR8 *PacketData + ); + + +/** ‘c [addr ]’ + Continue. addr is Address to resume. If addr is omitted, resume at current + Address. + + @param SystemContext Register content at time of the exception + @param *PacketData Pointer to PacketData + **/ + +VOID +ContinueAtAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ); + + +/** ‘s [addr ]’ + Single step. addr is the Address at which to resume. If addr is omitted, resume + at same Address. + + @param SystemContext Register content at time of the exception + @param PacketData Pointer to Payload data for the packet + **/ +VOID +SingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ); + +/** + Insert Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +AddSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + Remove Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +RemoveSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ); + + +/** + ‘Z1, [addr], [length]’ + ‘Z2, [addr], [length]’ + ‘Z3, [addr], [length]’ + ‘Z4, [addr], [length]’ + + Insert hardware breakpoint/watchpoint at address addr of size length + + @param SystemContext Register content at time of the exception + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +InsertBreakPoint( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ); + + +/** + ‘z1, [addr], [length]’ + ‘z2, [addr], [length]’ + ‘z3, [addr], [length]’ + ‘z4, [addr], [length]’ + + Remove hardware breakpoint/watchpoint at address addr of size length + + @param SystemContext Register content at time of the exception + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +RemoveBreakPoint( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ); + + +/** + Exception Hanldler for GDB. It will be called for all exceptions + registered via the gExceptionType[] array. + + @param ExceptionType Exception that is being processed + @param SystemContext Register content at time of the exception + + **/ +VOID +EFIAPI +GdbExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + + +/** + Periodic callback for GDB. This function is used to catch a ctrl-c or other + break in type command from GDB. + + @param SystemContext Register content at time of the call + + **/ +VOID +EFIAPI +GdbPeriodicCallBack ( + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + + +/** + Make two serail consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB. + + These console show up on the remote system running GDB + +**/ + +VOID +GdbInitializeSerialConsole ( + VOID + ); + + +/** + Send a GDB Remote Serial Protocol Packet + + $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', + the packet teminating character '#' and the two digit checksum. + + If an ack '+' is not sent resend the packet, but timeout eventually so we don't end up + in an infinit loop. This is so if you unplug the debugger code just keeps running + + @param PacketData Payload data for the packet + + @retval Number of bytes of packet data sent. + +**/ +UINTN +SendPacket ( + IN CHAR8 *PacketData + ); + + +/** + Receive a GDB Remote Serial Protocol Packet + + $PacketData#checksum PacketData is passed in and this function adds the packet prefix '$', + the packet teminating character '#' and the two digit checksum. + + If host re-starts sending a packet without ending the previous packet, only the last valid packet is proccessed. + (In other words, if received packet is '$12345$12345$123456#checksum', only '$123456#checksum' will be processed.) + + If an ack '+' is not sent resend the packet + + @param PacketData Payload data for the packet + + @retval Number of bytes of packet data received. + + **/ +UINTN +ReceivePacket ( + OUT CHAR8 *PacketData, + IN UINTN PacketDataSize + ); + + +/** + Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates + the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero. + + @param FileDescriptor Device to talk to. + @param Buffer Buffer to hold Count bytes that were read + @param Count Number of bytes to transfer. + + @retval -1 Error + @retval {other} Number of bytes read. + +**/ +INTN +GdbRead ( + IN INTN FileDescriptor, + OUT VOID *Buffer, + IN UINTN Count + ); + + +/** + Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates + nothing was written. On error -1 is returned. + + @param FileDescriptor Device to talk to. + @param Buffer Buffer to hold Count bytes that are to be written + @param Count Number of bytes to transfer. + + @retval -1 Error + @retval {other} Number of bytes written. + +**/ +INTN +GdbWrite ( + IN INTN FileDescriptor, + OUT CONST VOID *Buffer, + IN UINTN Count + ); + +UINTN * +FindPointerToRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber + ); + +CHAR8 * +BasicReadRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *OutBufPtr + ); + +VOID +TransferFromInBufToMem ( + IN UINTN Length, + IN UINT8 *Address, + IN CHAR8 *NewData + ); + +VOID +TransferFromMemToOutBufAndSend ( + IN UINTN Length, + IN UINT8 *Address + ); + +CHAR8 * +BasicWriteRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *InBufPtr + ); + +VOID +PrintReg ( + EFI_SYSTEM_CONTEXT SystemContext + ); + +UINTN +ParseBreakpointPacket ( + IN CHAR8 *PacketData, + OUT UINTN *Type, + OUT UINTN *Address, + OUT UINTN *Length + ); + +UINTN +GetBreakpointDataAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ); + +UINTN +GetBreakpointDetected ( + IN EFI_SYSTEM_CONTEXT SystemContext + ); + +BREAK_TYPE +GetBreakpointType ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ); + +UINTN +ConvertLengthData ( + IN UINTN Length + ); + +EFI_STATUS +FindNextFreeDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT UINTN *Register + ); + +EFI_STATUS +EnableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type + ); + +EFI_STATUS +FindMatchingDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type, + OUT UINTN *Register + ); + +EFI_STATUS +DisableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register + ); + +VOID +InitializeProcessor ( + VOID + ); + +BOOLEAN +ValidateAddress ( + IN VOID *Address + ); + +BOOLEAN +ValidateException ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +#endif diff --git a/EmbeddedPkg/GdbStub/Ia32/Processor.c b/EmbeddedPkg/GdbStub/Ia32/Processor.c new file mode 100644 index 0000000000..90a2224edf --- /dev/null +++ b/EmbeddedPkg/GdbStub/Ia32/Processor.c @@ -0,0 +1,993 @@ +/** @file + Processor specific parts of the GDB stub + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <GdbStubInternal.h> + +// +// Array of exception types that need to be hooked by the debugger +// {EFI mapping, GDB mapping} +// +EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = { + { EXCEPT_IA32_DIVIDE_ERROR, GDB_SIGFPE }, + { EXCEPT_IA32_DEBUG, GDB_SIGTRAP }, + { EXCEPT_IA32_NMI, GDB_SIGEMT }, + { EXCEPT_IA32_BREAKPOINT, GDB_SIGTRAP }, + { EXCEPT_IA32_OVERFLOW, GDB_SIGSEGV }, + { EXCEPT_IA32_BOUND, GDB_SIGSEGV }, + { EXCEPT_IA32_INVALID_OPCODE, GDB_SIGILL }, + { EXCEPT_IA32_DOUBLE_FAULT, GDB_SIGEMT }, + { EXCEPT_IA32_STACK_FAULT, GDB_SIGSEGV }, + { EXCEPT_IA32_GP_FAULT, GDB_SIGSEGV }, + { EXCEPT_IA32_PAGE_FAULT, GDB_SIGSEGV }, + { EXCEPT_IA32_FP_ERROR, GDB_SIGEMT }, + { EXCEPT_IA32_ALIGNMENT_CHECK, GDB_SIGEMT }, + { EXCEPT_IA32_MACHINE_CHECK, GDB_SIGEMT } +}; + + +// The offsets of registers SystemContext. +// The fields in the array are in the gdb ordering. +// +//16 regs +UINTN gRegisterOffsets[] = { + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eax), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ecx), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edx), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebx), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esp), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ebp), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Esi), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Edi), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eip), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Eflags), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Cs), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ss), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Ds), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Es), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Fs), + OFFSET_OF(EFI_SYSTEM_CONTEXT_IA32, Gs) +}; + + +//Debug only.. +VOID +PrintReg ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + Print ((CHAR16 *)L"EAX: %x ", SystemContext.SystemContextIa32->Eax); + Print ((CHAR16 *)L"ECX: %x ", SystemContext.SystemContextIa32->Ecx); + Print ((CHAR16 *)L"EDX: %x ", SystemContext.SystemContextIa32->Edx); + Print ((CHAR16 *)L"EBX: %x ", SystemContext.SystemContextIa32->Ebx); + Print ((CHAR16 *)L"ESP: %x ", SystemContext.SystemContextIa32->Esp); + Print ((CHAR16 *)L"EBP: %x ", SystemContext.SystemContextIa32->Ebp); + Print ((CHAR16 *)L"ESI: %x ", SystemContext.SystemContextIa32->Esi); + Print ((CHAR16 *)L"EDI: %x ", SystemContext.SystemContextIa32->Edi); + Print ((CHAR16 *)L"EIP: %x\n", SystemContext.SystemContextIa32->Eip); + Print ((CHAR16 *)L"EFlags: %x\n", SystemContext.SystemContextIa32->Eflags); +} + +//Debug only.. +VOID +PrintDRreg ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + Print ((CHAR16 *)L"DR0: %x ", SystemContext.SystemContextIa32->Dr0); + Print ((CHAR16 *)L"DR1: %x ", SystemContext.SystemContextIa32->Dr1); + Print ((CHAR16 *)L"DR2: %x ", SystemContext.SystemContextIa32->Dr2); + Print ((CHAR16 *)L"DR3: %x ", SystemContext.SystemContextIa32->Dr3); + Print ((CHAR16 *)L"DR6: %x ", SystemContext.SystemContextIa32->Dr6); + Print ((CHAR16 *)L"DR7: %x\n", SystemContext.SystemContextIa32->Dr7); +} + + +/** + Return the number of entries in the gExceptionType[] + + @retval UINTN, the number of entries in the gExceptionType[] array. + **/ +UINTN +MaxEfiException ( + VOID + ) +{ + return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY); +} + + +/** + Return the number of entries in the gRegisters[] + + @retval UINTN, the number of entries (registers) in the gRegisters[] array. + **/ +UINTN +MaxRegisterCount ( + VOID + ) +{ + return sizeof (gRegisterOffsets)/sizeof (UINTN); +} + + +/** + Check to see if the ISA is supported. + ISA = Instruction Set Architecture + + @retval TRUE if Isa is supported, + FALSE otherwise. +**/ +BOOLEAN +CheckIsa ( + IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa + ) +{ + return (BOOLEAN)(Isa == IsaIa32); +} + + +/** + This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering + It is, by default, set to find the register pointer of the IA32 member + + @param SystemContext Register content at time of the exception + @param RegNumber The register to which we want to find a pointer + @retval the pointer to the RegNumber-th pointer + **/ +UINTN * +FindPointerToRegister( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber + ) +{ + UINT8 *TempPtr; + TempPtr = ((UINT8 *)SystemContext.SystemContextIa32) + gRegisterOffsets[RegNumber]; + return (UINTN *)TempPtr; +} + + +/** + Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr + + @param SystemContext Register content at time of the exception + @param RegNumber the number of the register that we want to read + @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on. + @retval the pointer to the next character of the output buffer that is available to be written on. + **/ +CHAR8 * +BasicReadRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *OutBufPtr + ) +{ + UINTN RegSize; + + RegSize = 0; + while (RegSize < REG_SIZE) { + *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)]; + *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)]; + RegSize = RegSize + 8; + } + return OutBufPtr; +} + + +/** ‘p n’ + Reads the n-th register's value into an output buffer and sends it as a packet + + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ +VOID +EFIAPI +ReadNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN RegNumber; + CHAR8 OutBuffer[9]; // 1 reg=8 hex chars, and the end '\0' (escape seq) + CHAR8 *OutBufPtr; // pointer to the output buffer + + RegNumber = AsciiStrHexToUintn (&InBuffer[1]); + + if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) { + SendError (GDB_EINVALIDREGNUM); + return; + } + + OutBufPtr = OutBuffer; + OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr); + + *OutBufPtr = '\0'; // the end of the buffer + SendPacket(OutBuffer); +} + + +/** ‘g’ + Reads the general registers into an output buffer and sends it as a packet + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +ReadGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINTN i; + CHAR8 OutBuffer[129]; // 16 regs, 8 hex chars each, and the end '\0' (escape seq) + CHAR8 *OutBufPtr; // pointer to the output buffer + + OutBufPtr = OutBuffer; + for(i = 0 ; i < MaxRegisterCount() ; i++) { // there are only 16 registers to read + OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr); + } + + *OutBufPtr = '\0'; // the end of the buffer + SendPacket(OutBuffer); +} + + +/** + Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr + + @param SystemContext Register content at time of the exception + @param RegNumber the number of the register that we want to write + @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on. + @retval the pointer to the next character of the input buffer that can be used + **/ +CHAR8 * +BasicWriteRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN RegNumber, + IN CHAR8 *InBufPtr + ) +{ + UINTN RegSize; + UINTN TempValue; // the value transferred from a hex char + UINT32 NewValue; // the new value of the RegNumber-th Register + + NewValue = 0; + RegSize = 0; + while (RegSize < REG_SIZE) { + TempValue = HexCharToInt(*InBufPtr++); + + if (TempValue < 0) { + SendError (GDB_EBADMEMDATA); + return NULL; + } + + NewValue += (TempValue << (RegSize+4)); + TempValue = HexCharToInt(*InBufPtr++); + + if (TempValue < 0) { + SendError (GDB_EBADMEMDATA); + return NULL; + } + + NewValue += (TempValue << RegSize); + RegSize = RegSize + 8; + } + *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue; + return InBufPtr; +} + + +/** ‘P n...=r...’ + Writes the new value of n-th register received into the input buffer to the n-th register + + @param SystemContext Register content at time of the exception + @param InBuffer Ponter to the input buffer received from gdb server + **/ +VOID +EFIAPI +WriteNthRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN RegNumber; + CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array + CHAR8 *RegNumBufPtr; + CHAR8 *InBufPtr; // pointer to the input buffer + + // find the register number to write + InBufPtr = &InBuffer[1]; + RegNumBufPtr = RegNumBuffer; + while (*InBufPtr != '=') { + *RegNumBufPtr++ = *InBufPtr++; + } + *RegNumBufPtr = '\0'; + RegNumber = AsciiStrHexToUintn (RegNumBuffer); + + // check if this is a valid Register Number + if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) { + SendError (GDB_EINVALIDREGNUM); + return; + } + InBufPtr++; // skips the '=' character + BasicWriteRegister (SystemContext, RegNumber, InBufPtr); + SendSuccess(); +} + + +/** ‘G XX...’ + Writes the new values received into the input buffer to the general registers + + @param SystemContext Register content at time of the exception + @param InBuffer Pointer to the input buffer received from gdb server + **/ +VOID +EFIAPI +WriteGeneralRegisters ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *InBuffer + ) +{ + UINTN i; + CHAR8 *InBufPtr; /// pointer to the input buffer + + // check to see if the buffer is the right size which is + // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 129 + if (AsciiStrLen(InBuffer) != 129) { // 16 regs, 8 hex chars each, and the end '\0' (escape seq) + //Bad message. Message is not the right length + SendError (GDB_EBADBUFSIZE); + return; + } + + InBufPtr = &InBuffer[1]; + + // Read the new values for the registers from the input buffer to an array, NewValueArray. + // The values in the array are in the gdb ordering + for(i=0; i < MaxRegisterCount(); i++) { // there are only 16 registers to write + InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr); + } + + SendSuccess(); +} + + +/** + Insert Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +AddSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + SystemContext.SystemContextIa32->Eflags |= TF_BIT; //Setting the TF bit. +} + + +/** + Remove Single Step in the SystemContext + + @param SystemContext Register content at time of the exception + **/ +VOID +RemoveSingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + SystemContext.SystemContextIa32->Eflags &= ~TF_BIT; // clearing the TF bit. +} + + + +/** ‘c [addr ]’ + Continue. addr is Address to resume. If addr is omitted, resume at current + Address. + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +ContinueAtAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + if (PacketData[1] != '\0') { + SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]); + } +} + + +/** ‘s [addr ]’ + Single step. addr is the Address at which to resume. If addr is omitted, resume + at same Address. + + @param SystemContext Register content at time of the exception + **/ +VOID +EFIAPI +SingleStep ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + if (PacketData[1] != '\0') { + SystemContext.SystemContextIa32->Eip = AsciiStrHexToUintn (&PacketData[1]); + } + + AddSingleStep (SystemContext); +} + + +/** + Returns breakpoint data address from DR0-DR3 based on the input breakpoint number + + @param SystemContext Register content at time of the exception + @param BreakpointNumber Breakpoint number + + @retval Address Data address from DR0-DR3 based on the breakpoint number. + +**/ +UINTN +GetBreakpointDataAddress ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ) +{ + UINTN Address; + + if (BreakpointNumber == 1) { + Address = SystemContext.SystemContextIa32->Dr0; + } else if (BreakpointNumber == 2) { + Address = SystemContext.SystemContextIa32->Dr1; + } else if (BreakpointNumber == 3) { + Address = SystemContext.SystemContextIa32->Dr2; + } else if (BreakpointNumber == 4) { + Address = SystemContext.SystemContextIa32->Dr3; + } else { + Address = 0; + } + + return Address; +} + + +/** + Returns currently detected breakpoint value based on the register DR6 B0-B3 field. + If no breakpoint is detected then it returns 0. + + @param SystemContext Register content at time of the exception + + @retval {1-4} Currently detected breakpoint value + @retval 0 No breakpoint detected. + +**/ +UINTN +GetBreakpointDetected ( + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + IA32_DR6 Dr6; + UINTN BreakpointNumber; + + Dr6.UintN = SystemContext.SystemContextIa32->Dr6; + + if (Dr6.Bits.B0 == 1) { + BreakpointNumber = 1; + } else if (Dr6.Bits.B1 == 1) { + BreakpointNumber = 2; + } else if (Dr6.Bits.B2 == 1) { + BreakpointNumber = 3; + } else if (Dr6.Bits.B3 == 1) { + BreakpointNumber = 4; + } else { + BreakpointNumber = 0; //No breakpoint detected + } + + return BreakpointNumber; +} + + +/** + Returns Breakpoint type (InstructionExecution, DataWrite, DataRead or DataReadWrite) + based on the Breakpoint number + + @param SystemContext Register content at time of the exception + @param BreakpointNumber Breakpoint number + + @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn field + For unknown value, it returns NotSupported. + +**/ +BREAK_TYPE +GetBreakpointType ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN BreakpointNumber + ) +{ + IA32_DR7 Dr7; + BREAK_TYPE Type = NotSupported; //Default is NotSupported type + + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (BreakpointNumber == 1) { + Type = (BREAK_TYPE) Dr7.Bits.RW0; + } else if (BreakpointNumber == 2) { + Type = (BREAK_TYPE) Dr7.Bits.RW1; + } else if (BreakpointNumber == 3) { + Type = (BREAK_TYPE) Dr7.Bits.RW2; + } else if (BreakpointNumber == 4) { + Type = (BREAK_TYPE) Dr7.Bits.RW3; + } + + return Type; +} + + +/** + Parses Length and returns the length which DR7 LENn field accepts. + For example: If we receive 1-Byte length then we should return 0. + Zero gets written to DR7 LENn field. + + @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte) + + @retval Length Appropriate converted values which DR7 LENn field accepts. + +**/ +UINTN +ConvertLengthData ( + IN UINTN Length + ) +{ + if (Length == 1) { //1-Byte length + return 0; + } else if (Length == 2) { //2-Byte length + return 1; + } else if (Length == 4) { //4-Byte length + return 3; + } else { //Undefined or 8-byte length + return 2; + } +} + + +/** + Finds the next free debug register. If all the registers are occupied then + EFI_OUT_OF_RESOURCES is returned. + + @param SystemContext Register content at time of the exception + @param Register Register value (0 - 3 for the first free debug register) + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +FindNextFreeDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + OUT UINTN *Register + ) +{ + IA32_DR7 Dr7; + + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (Dr7.Bits.G0 == 0) { + *Register = 0; + } else if (Dr7.Bits.G1 == 0) { + *Register = 1; + } else if (Dr7.Bits.G2 == 0) { + *Register = 2; + } else if (Dr7.Bits.G3 == 0) { + *Register = 3; + } else { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + + +/** + Enables the debug register. Writes Address value to appropriate DR0-3 register. + Sets LENn, Gn, RWn bits in DR7 register. + + @param SystemContext Register content at time of the exception + @param Register Register value (0 - 3) + @param Address Breakpoint address value + @param Type Breakpoint type (Instruction, Data write, Data read + or write etc.) + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +EnableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type + ) +{ + IA32_DR7 Dr7; + + //Convert length data + Length = ConvertLengthData (Length); + + //For Instruction execution, length should be 0 + //(Ref. Intel reference manual 18.2.4) + if ((Type == 0) && (Length != 0)) { + return EFI_INVALID_PARAMETER; + } + + //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle + //software breakpoint. We should send empty packet in both these cases. + if ((Type == (BREAK_TYPE)DataRead) || + (Type == (BREAK_TYPE)SoftwareBreakpoint)) { + return EFI_UNSUPPORTED; + } + + //Read DR7 so appropriate Gn, RWn and LENn bits can be modified. + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (Register == 0) { + SystemContext.SystemContextIa32->Dr0 = Address; + Dr7.Bits.G0 = 1; + Dr7.Bits.RW0 = Type; + Dr7.Bits.LEN0 = Length; + } else if (Register == 1) { + SystemContext.SystemContextIa32->Dr1 = Address; + Dr7.Bits.G1 = 1; + Dr7.Bits.RW1 = Type; + Dr7.Bits.LEN1 = Length; + } else if (Register == 2) { + SystemContext.SystemContextIa32->Dr2 = Address; + Dr7.Bits.G2 = 1; + Dr7.Bits.RW2 = Type; + Dr7.Bits.LEN2 = Length; + } else if (Register == 3) { + SystemContext.SystemContextIa32->Dr3 = Address; + Dr7.Bits.G3 = 1; + Dr7.Bits.RW3 = Type; + Dr7.Bits.LEN3 = Length; + } else { + return EFI_INVALID_PARAMETER; + } + + //Update Dr7 with appropriate Gn, RWn and LENn bits + SystemContext.SystemContextIa32->Dr7 = Dr7.UintN; + + return EFI_SUCCESS; +} + + +/** + Returns register number 0 - 3 for the maching debug register. + This function compares incoming Address, Type, Length and + if there is a match then it returns the appropriate register number. + In case of mismatch, function returns EFI_NOT_FOUND message. + + @param SystemContext Register content at time of the exception + @param Address Breakpoint address value + @param Length Breakpoint length value + @param Type Breakpoint type (Instruction, Data write, + Data read or write etc.) + @param Register Register value to be returned + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +FindMatchingDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Address, + IN UINTN Length, + IN UINTN Type, + OUT UINTN *Register + ) +{ + IA32_DR7 Dr7; + + //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle + //software breakpoint. We should send empty packet in both these cases. + if ((Type == (BREAK_TYPE)DataRead) || + (Type == (BREAK_TYPE)SoftwareBreakpoint)) { + return EFI_UNSUPPORTED; + } + + //Convert length data + Length = ConvertLengthData(Length); + + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if ((Dr7.Bits.G0 == 1) && + (Dr7.Bits.LEN0 == Length) && + (Dr7.Bits.RW0 == Type) && + (Address == SystemContext.SystemContextIa32->Dr0)) { + *Register = 0; + } else if ((Dr7.Bits.G1 == 1) && + (Dr7.Bits.LEN1 == Length) && + (Dr7.Bits.RW1 == Type) && + (Address == SystemContext.SystemContextIa32->Dr1)) { + *Register = 1; + } else if ((Dr7.Bits.G2 == 1) && + (Dr7.Bits.LEN2 == Length) && + (Dr7.Bits.RW2 == Type) && + (Address == SystemContext.SystemContextIa32->Dr2)) { + *Register = 2; + } else if ((Dr7.Bits.G3 == 1) && + (Dr7.Bits.LEN3 == Length) && + (Dr7.Bits.RW3 == Type) && + (Address == SystemContext.SystemContextIa32->Dr3)) { + *Register = 3; + } else { + Print ((CHAR16 *)L"No match found..\n"); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + + +/** + Disables the particular debug register. + + @param SystemContext Register content at time of the exception + @param Register Register to be disabled + + @retval EFI_STATUS Appropriate status value. + +**/ +EFI_STATUS +DisableDebugRegister ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN UINTN Register + ) +{ + IA32_DR7 Dr7; + UINTN Address = 0; + + //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off. + Dr7.UintN = SystemContext.SystemContextIa32->Dr7; + + if (Register == 0) { + SystemContext.SystemContextIa32->Dr0 = Address; + Dr7.Bits.G0 = 0; + Dr7.Bits.RW0 = 0; + Dr7.Bits.LEN0 = 0; + } else if (Register == 1) { + SystemContext.SystemContextIa32->Dr1 = Address; + Dr7.Bits.G1 = 0; + Dr7.Bits.RW1 = 0; + Dr7.Bits.LEN1 = 0; + } else if (Register == 2) { + SystemContext.SystemContextIa32->Dr2 = Address; + Dr7.Bits.G2 = 0; + Dr7.Bits.RW2 = 0; + Dr7.Bits.LEN2 = 0; + } else if (Register == 3) { + SystemContext.SystemContextIa32->Dr3 = Address; + Dr7.Bits.G3 = 0; + Dr7.Bits.RW3 = 0; + Dr7.Bits.LEN3 = 0; + } else { + return EFI_INVALID_PARAMETER; + } + + //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off. + SystemContext.SystemContextIa32->Dr7 = Dr7.UintN; + + return EFI_SUCCESS; +} + + +/** + ‘Z1, [addr], [length]’ + ‘Z2, [addr], [length]’ + ‘Z3, [addr], [length]’ + ‘Z4, [addr], [length]’ + + Insert hardware breakpoint/watchpoint at address addr of size length + + @param SystemContext Register content at time of the exception + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +InsertBreakPoint ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + UINTN Type; + UINTN Address; + UINTN Length; + UINTN Register; + EFI_STATUS Status; + BREAK_TYPE BreakType = NotSupported; + UINTN ErrorCode; + + ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length); + if (ErrorCode > 0) { + SendError ((UINT8)ErrorCode); + return; + } + + switch (Type) { + + case 0: //Software breakpoint + BreakType = SoftwareBreakpoint; + break; + + case 1: //Hardware breakpoint + BreakType = InstructionExecution; + break; + + case 2: //Write watchpoint + BreakType = DataWrite; + break; + + case 3: //Read watchpoint + BreakType = DataRead; + break; + + case 4: //Access watchpoint + BreakType = DataReadWrite; + break; + + default : + Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type); + SendError (GDB_EINVALIDBRKPOINTTYPE); + return; + } + + // Find next free debug register + Status = FindNextFreeDebugRegister (SystemContext, &Register); + if (EFI_ERROR(Status)) { + Print ((CHAR16 *)L"No space left on device\n"); + SendError (GDB_ENOSPACE); + return; + } + + // Write Address, length data at particular DR register + Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType); + if (EFI_ERROR(Status)) { + + if (Status == EFI_UNSUPPORTED) { + Print ((CHAR16 *)L"Not supported\n"); + SendNotSupported(); + return; + } + + Print ((CHAR16 *)L"Invalid argument\n"); + SendError (GDB_EINVALIDARG); + return; + } + + SendSuccess (); +} + + +/** + ‘z1, [addr], [length]’ + ‘z2, [addr], [length]’ + ‘z3, [addr], [length]’ + ‘z4, [addr], [length]’ + + Remove hardware breakpoint/watchpoint at address addr of size length + + @param *PacketData Pointer to the Payload data for the packet + +**/ +VOID +EFIAPI +RemoveBreakPoint ( + IN EFI_SYSTEM_CONTEXT SystemContext, + IN CHAR8 *PacketData + ) +{ + UINTN Type; + UINTN Address; + UINTN Length; + UINTN Register; + BREAK_TYPE BreakType = NotSupported; + EFI_STATUS Status; + UINTN ErrorCode; + + //Parse breakpoint packet data + ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length); + if (ErrorCode > 0) { + SendError ((UINT8)ErrorCode); + return; + } + + switch (Type) { + + case 0: //Software breakpoint + BreakType = SoftwareBreakpoint; + break; + + case 1: //Hardware breakpoint + BreakType = InstructionExecution; + break; + + case 2: //Write watchpoint + BreakType = DataWrite; + break; + + case 3: //Read watchpoint + BreakType = DataRead; + break; + + case 4: //Access watchpoint + BreakType = DataReadWrite; + break; + + default : + SendError (GDB_EINVALIDBRKPOINTTYPE); + return; + } + + //Find matching debug register + Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register); + if (EFI_ERROR(Status)) { + + if (Status == EFI_UNSUPPORTED) { + Print ((CHAR16 *)L"Not supported.\n"); + SendNotSupported(); + return; + } + + Print ((CHAR16 *)L"No matching register found.\n"); + SendError (GDB_ENOSPACE); + return; + } + + //Remove breakpoint + Status = DisableDebugRegister(SystemContext, Register); + if (EFI_ERROR(Status)) { + Print ((CHAR16 *)L"Invalid argument.\n"); + SendError (GDB_EINVALIDARG); + return; + } + + SendSuccess (); +} + + +VOID +InitializeProcessor ( + VOID + ) +{ +} + +BOOLEAN +ValidateAddress ( + IN VOID *Address + ) +{ + return TRUE; +} + +BOOLEAN +ValidateException ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ) +{ + return TRUE; +} + diff --git a/EmbeddedPkg/GdbStub/SerialIo.c b/EmbeddedPkg/GdbStub/SerialIo.c new file mode 100644 index 0000000000..5afaed06b9 --- /dev/null +++ b/EmbeddedPkg/GdbStub/SerialIo.c @@ -0,0 +1,551 @@ +/** @file + Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system + running GDB. One consle for error information and another console for user input/output. + + Basic packet format is $packet-data#checksum. So every comand has 4 bytes of overhead: $, + #, 0, 0. The 0 and 0 are the ascii characters for the checksum. + + + Copyright (c) 2008-2009, Apple Inc. All rights reserved. + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include <GdbStubInternal.h> + +// +// Set TRUE if F Reply package signals a ctrl-c. We can not process the Ctrl-c +// here we need to wait for the periodic callback to do this. +// +BOOLEAN gCtrlCBreakFlag = FALSE; + +// +// If the periodic callback is called while we are processing an F packet we need +// to let the callback know to not read from the serail stream as it could steal +// characters from the F reponse packet +// +BOOLEAN gProcessingFPacket = FALSE; + +/** + Process a control-C break message. + + Currently a place holder, remove the ASSERT when it gets implemented. + + @param ErrNo Error infomration from the F reply packet or other source + +**/ + +VOID +GdbCtrlCBreakMessage ( + IN UINTN ErrNo + ) +{ + // See D.10.5 of gdb.pdf + // This should look like a break message. Should look like SIGINT + + /* TODO: Make sure if we should do anything with ErrNo */ + //Turn on the global Ctrl-C flag. + gCtrlCBreakFlag = TRUE; +} + + +/** + Parse the F reply packet and extract the return value and an ErrNo if it exists. + + @param Packet Packet to parse like an F reply packet + @param ErrNo Buffer to hold Count bytes that were read + + @retval -1 Error, not a valid F reply packet + @retval other Return the return code from the F reply packet + +**/ +INTN +GdbParseFReplyPacket ( + IN CHAR8 *Packet, + OUT UINTN *ErrNo + ) +{ + INTN RetCode; + + if (Packet[0] != 'F') { + // A valid responce would be an F packet + return -1; + } + + RetCode = AsciiStrHexToUintn (&Packet[1]); + + // Find 1st comma + for (;*Packet != '\0' && *Packet != ','; Packet++); + if (*Packet == '\0') { + *ErrNo = 0; + return RetCode; + } + + *ErrNo = AsciiStrHexToUintn (++Packet); + + // Find 2nd comma + for (;*Packet != '\0' && *Packet != ','; Packet++); + if (*Packet == '\0') { + return RetCode; + } + + if (*(++Packet) == 'C') { + GdbCtrlCBreakMessage (*ErrNo); + } + + return RetCode; +} + + +/** + Read data from a FileDescriptor. On success number of bytes read is returned. Zero indicates + the end of a file. On error -1 is returned. If count is zero, GdbRead returns zero. + + @param FileDescriptor Device to talk to. + @param Buffer Buffer to hold Count bytes that were read + @param Count Number of bytes to transfer. + + @retval -1 Error + @retval {other} Number of bytes read. + +**/ +INTN +GdbRead ( + IN INTN FileDescriptor, + OUT VOID *Buffer, + IN UINTN Count + ) +{ + CHAR8 Packet[128]; + UINTN Size; + INTN RetCode; + UINTN ErrNo; + BOOLEAN ReceiveDone = FALSE; + + // Send: + // "Fread,XX,YYYYYYYY,XX + // + // XX - FileDescriptor in ASCII + // YYYYYYYY - Buffer address in ASCII + // XX - Count in ASCII + // SS - check sum + // + Size = AsciiSPrint (Packet, sizeof (Packet), "Fread,%x,%x,%x", FileDescriptor, Buffer, Count); + // Packet array is too small if you got this ASSERT + ASSERT (Size < sizeof (Packet)); + + gProcessingFPacket = TRUE; + SendPacket (Packet); + Print ((CHAR16 *)L"Packet sent..\n"); + + do { + // Reply: + ReceivePacket (Packet, sizeof (Packet)); + Print ((CHAR16 *)L"Command received..%c\n", Packet[0]); + + // Process GDB commands + switch (Packet[0]) { + //Write memory command. + //M addr,length:XX... + case 'M': + WriteToMemory (Packet); + break; + + //Fretcode, errno, Ctrl-C flag + //retcode - Count read + case 'F': + //Once target receives F reply packet that means the previous + //transactions are finished. + ReceiveDone = TRUE; + break; + + //Send empty buffer + default : + SendNotSupported(); + break; + } + } while (ReceiveDone == FALSE); + + RetCode = GdbParseFReplyPacket (Packet, &ErrNo); + Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo); + + if (ErrNo > 0) { + //Send error to the host if there is any. + SendError ((UINT8)ErrNo); + } + + gProcessingFPacket = FALSE; + + return RetCode; +} + + +/** + Write data to a FileDescriptor. On success number of bytes written is returned. Zero indicates + nothing was written. On error -1 is returned. + + @param FileDescriptor Device to talk to. + @param Buffer Buffer to hold Count bytes that are to be written + @param Count Number of bytes to transfer. + + @retval -1 Error + @retval {other} Number of bytes written. + +**/ +INTN +GdbWrite ( + IN INTN FileDescriptor, + OUT CONST VOID *Buffer, + IN UINTN Count + ) +{ + CHAR8 Packet[128]; + UINTN Size; + INTN RetCode; + UINTN ErrNo; + BOOLEAN ReceiveDone = FALSE; + + // Send: + // #Fwrite,XX,YYYYYYYY,XX$SS + // + // XX - FileDescriptor in ASCII + // YYYYYYYY - Buffer address in ASCII + // XX - Count in ASCII + // SS - check sum + // + Size = AsciiSPrint (Packet, sizeof (Packet), "Fwrite,%x,%x,%x", FileDescriptor, Buffer, Count); + // Packet array is too small if you got this ASSERT + ASSERT (Size < sizeof (Packet)); + + SendPacket (Packet); + Print ((CHAR16 *)L"Packet sent..\n"); + + do { + // Reply: + ReceivePacket (Packet, sizeof (Packet)); + Print ((CHAR16 *)L"Command received..%c\n", Packet[0]); + + // Process GDB commands + switch (Packet[0]) { + //Read memory command. + //m addr,length. + case 'm': + ReadFromMemory (Packet); + break; + + //Fretcode, errno, Ctrl-C flag + //retcode - Count read + case 'F': + //Once target receives F reply packet that means the previous + //transactions are finished. + ReceiveDone = TRUE; + break; + + //Send empty buffer + default : + SendNotSupported(); + break; + } + } while (ReceiveDone == FALSE); + + RetCode = GdbParseFReplyPacket (Packet, &ErrNo); + Print ((CHAR16 *)L"RetCode: %x..ErrNo: %x..\n", RetCode, ErrNo); + + //Send error to the host if there is any. + if (ErrNo > 0) { + SendError((UINT8)ErrNo); + } + + return RetCode; +} + + +/** + Reset the serial device. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The serial device could not be reset. + +**/ +EFI_STATUS +EFIAPI +GdbSerialReset ( + IN EFI_SERIAL_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} + + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data buts, and stop bits on a serial device. + + @param This Protocol instance pointer. + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the + device's default interface speed. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's dfault FIFO depth. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The serial device could not be reset. + +**/ +EFI_STATUS +EFIAPI +GdbSerialSetAttributes ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Set the control bits on a serial device + + @param This Protocol instance pointer. + @param Control Set the bits of Control that are settable. + + @retval EFI_SUCCESS The new control bits were set on the serial device. + @retval EFI_UNSUPPORTED The serial device does not support this operation. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +EFI_STATUS +EFIAPI +GdbSerialSetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Retrieves the status of thecontrol bits on a serial device + + @param This Protocol instance pointer. + @param Control A pointer to return the current Control signals from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +EFI_STATUS +EFIAPI +GdbSerialGetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data actually written. + @param Buffer The buffer of data to write + + @retval EFI_SUCCESS The data was written. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ +EFI_STATUS +EFIAPI +GdbSerialWrite ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + GDB_SERIAL_DEV *SerialDev; + UINTN Return; + + SerialDev = GDB_SERIAL_DEV_FROM_THIS (This); + + Return = GdbWrite (SerialDev->OutFileDescriptor, Buffer, *BufferSize); + if (Return == (UINTN)-1) { + return EFI_DEVICE_ERROR; + } + + if (Return != *BufferSize) { + *BufferSize = Return; + } + + return EFI_SUCCESS; +} + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data returned in Buffer. + @param Buffer The buffer to return the data into. + + @retval EFI_SUCCESS The data was read. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ + +EFI_STATUS +EFIAPI +GdbSerialRead ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + GDB_SERIAL_DEV *SerialDev; + UINTN Return; + + SerialDev = GDB_SERIAL_DEV_FROM_THIS (This); + + Return = GdbRead (SerialDev->InFileDescriptor, Buffer, *BufferSize); + if (Return == (UINTN)-1) { + return EFI_DEVICE_ERROR; + } + + if (Return != *BufferSize) { + *BufferSize = Return; + } + + return EFI_SUCCESS; +} + + +// +// Template used to initailize the GDB Serial IO protocols +// +GDB_SERIAL_DEV gdbSerialDevTemplate = { + GDB_SERIAL_DEV_SIGNATURE, + NULL, + + { // SerialIo + SERIAL_IO_INTERFACE_REVISION, + GdbSerialReset, + GdbSerialSetAttributes, + GdbSerialSetControl, + GdbSerialGetControl, + GdbSerialWrite, + GdbSerialRead, + NULL + }, + { // SerialMode + 0, // ControlMask + 0, // Timeout + 0, // BaudRate + 1, // RceiveFifoDepth + 0, // DataBits + 0, // Parity + 0 // StopBits + }, + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH) + sizeof (UINT32)) >> 8) + }, + EFI_SERIAL_IO_PROTOCOL_GUID, + }, + 0, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL)), + (UINT8) (sizeof (EFI_DEVICE_PATH_PROTOCOL) >> 8) + } + }, + }, + GDB_STDIN, + GDB_STDOUT +}; + + +/** + Make two serial consoles: 1) StdIn and StdOut via GDB. 2) StdErr via GDB. + + These console show up on the remote system running GDB + +**/ +VOID +GdbInitializeSerialConsole ( + VOID + ) +{ + EFI_STATUS Status; + GDB_SERIAL_DEV *StdOutSerialDev; + GDB_SERIAL_DEV *StdErrSerialDev; + + // Use the template to make a copy of the Serial Console private data structure. + StdOutSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV), &gdbSerialDevTemplate); + ASSERT (StdOutSerialDev != NULL); + + // Fixup pointer after the copy + StdOutSerialDev->SerialIo.Mode = &StdOutSerialDev->SerialMode; + + StdErrSerialDev = AllocateCopyPool (sizeof (GDB_SERIAL_DEV), &gdbSerialDevTemplate); + ASSERT (StdErrSerialDev != NULL); + + // Fixup pointer and modify stuff that is different for StdError + StdErrSerialDev->SerialIo.Mode = &StdErrSerialDev->SerialMode; + StdErrSerialDev->DevicePath.Index = 1; + StdErrSerialDev->OutFileDescriptor = GDB_STDERR; + + // Make a new handle with Serial IO protocol and its device path on it. + Status = gBS->InstallMultipleProtocolInterfaces ( + &StdOutSerialDev->Handle, + &gEfiSerialIoProtocolGuid, &StdOutSerialDev->SerialIo, + &gEfiDevicePathProtocolGuid, &StdOutSerialDev->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // Make a new handle with Serial IO protocol and its device path on it. + Status = gBS->InstallMultipleProtocolInterfaces ( + &StdErrSerialDev->Handle, + &gEfiSerialIoProtocolGuid, &StdErrSerialDev->SerialIo, + &gEfiDevicePathProtocolGuid, &StdErrSerialDev->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); +} + diff --git a/EmbeddedPkg/GdbStub/X64/Processor.c b/EmbeddedPkg/GdbStub/X64/Processor.c new file mode 100644 index 0000000000..0758bc4a84 --- /dev/null +++ b/EmbeddedPkg/GdbStub/X64/Processor.c @@ -0,0 +1,963 @@ +/** @file
+ Processor specific parts of the GDB stub
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <GdbStubInternal.h>
+
+//
+// Array of exception types that need to be hooked by the debugger
+//
+EFI_EXCEPTION_TYPE_ENTRY gExceptionType[] = {
+ { EXCEPT_X64_DIVIDE_ERROR, GDB_SIGFPE },
+ { EXCEPT_X64_DEBUG, GDB_SIGTRAP },
+ { EXCEPT_X64_NMI, GDB_SIGEMT },
+ { EXCEPT_X64_BREAKPOINT, GDB_SIGTRAP },
+ { EXCEPT_X64_OVERFLOW, GDB_SIGSEGV },
+ { EXCEPT_X64_BOUND, GDB_SIGSEGV },
+ { EXCEPT_X64_INVALID_OPCODE, GDB_SIGILL },
+ { EXCEPT_X64_DOUBLE_FAULT, GDB_SIGEMT },
+ { EXCEPT_X64_STACK_FAULT, GDB_SIGSEGV },
+ { EXCEPT_X64_GP_FAULT, GDB_SIGSEGV },
+ { EXCEPT_X64_PAGE_FAULT, GDB_SIGSEGV },
+ { EXCEPT_X64_FP_ERROR, GDB_SIGEMT },
+ { EXCEPT_X64_ALIGNMENT_CHECK, GDB_SIGEMT },
+ { EXCEPT_X64_MACHINE_CHECK, GDB_SIGEMT }
+};
+
+
+// The offsets of registers SystemContextX64.
+// The fields in the array are in the gdb ordering.
+// HAVE TO DOUBLE-CHECK THE ORDER of the 24 regs
+//
+UINTN gRegisterOffsets[] = {
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rax),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rcx),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdx),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbx),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsp),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rbp),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rsi),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rdi),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rip),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Rflags),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Cs),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ss),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Ds),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Es),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Fs),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, Gs),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R8),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R9),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R10),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R11),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R12),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R13),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R14),
+ OFFSET_OF(EFI_SYSTEM_CONTEXT_X64, R15)
+};
+
+
+/**
+ Return the number of entries in the gExceptionType[]
+
+ @retval UINTN, the number of entries in the gExceptionType[] array.
+ **/
+UINTN
+MaxEfiException (
+ VOID
+ )
+{
+ return sizeof (gExceptionType)/sizeof (EFI_EXCEPTION_TYPE_ENTRY);
+}
+
+
+/**
+ Return the number of entries in the gRegisters[]
+
+ @retval UINTN, the number of entries (registers) in the gRegisters[] array.
+ **/
+UINTN
+MaxRegisterCount (
+ VOID
+ )
+{
+ return sizeof (gRegisterOffsets)/sizeof (UINTN);
+}
+
+
+/**
+ Check to see if the ISA is supported.
+ ISA = Instruction Set Architecture
+
+ @retval TRUE if Isa is supported
+**/
+BOOLEAN
+CheckIsa (
+ IN EFI_INSTRUCTION_SET_ARCHITECTURE Isa
+ )
+{
+ return (BOOLEAN)(Isa == IsaX64);
+}
+
+
+/**
+ This takes in the register number and the System Context, and returns a pointer to the RegNumber-th register in gdb ordering
+ It is, by default, set to find the register pointer of the X64 member
+ @param SystemContext Register content at time of the exception
+ @param RegNumber The register to which we want to find a pointer
+ @retval the pointer to the RegNumber-th pointer
+ **/
+UINTN *
+FindPointerToRegister(
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN RegNumber
+ )
+{
+ UINT8 *TempPtr;
+ TempPtr = ((UINT8 *)SystemContext.SystemContextX64) + gRegisterOffsets[RegNumber];
+ return (UINTN *)TempPtr;
+}
+
+
+/**
+ Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
+ @param SystemContext Register content at time of the exception
+ @param RegNumber the number of the register that we want to read
+ @param OutBufPtr pointer to the output buffer's end. the new data will be added from this point on.
+ @retval the pointer to the next character of the output buffer that is available to be written on.
+ **/
+CHAR8 *
+BasicReadRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN RegNumber,
+ IN CHAR8 *OutBufPtr
+ )
+{
+ UINTN RegSize;
+
+ RegSize = 0;
+ while (RegSize < 64) {
+ *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> (RegSize+4)) & 0xf)];
+ *OutBufPtr++ = mHexToStr[((*FindPointerToRegister(SystemContext, RegNumber) >> RegSize) & 0xf)];
+ RegSize = RegSize + 8;
+ }
+ return OutBufPtr;
+}
+
+
+/** ‘p n’
+ Reads the n-th register's value into an output buffer and sends it as a packet
+ @param SystemContext Register content at time of the exception
+ @param InBuffer Pointer to the input buffer received from gdb server
+ **/
+VOID
+ReadNthRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *InBuffer
+ )
+{
+ UINTN RegNumber;
+ CHAR8 OutBuffer[17]; // 1 reg=16 hex chars, and the end '\0' (escape seq)
+ CHAR8 *OutBufPtr; // pointer to the output buffer
+
+ RegNumber = AsciiStrHexToUintn (&InBuffer[1]);
+
+ if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {
+ SendError (GDB_EINVALIDREGNUM);
+ return;
+ }
+
+ OutBufPtr = OutBuffer;
+ OutBufPtr = BasicReadRegister(SystemContext, RegNumber, OutBufPtr);
+
+ *OutBufPtr = '\0'; // the end of the buffer
+ SendPacket (OutBuffer);
+}
+
+
+/** ‘g’
+ Reads the general registers into an output buffer and sends it as a packet
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+EFIAPI
+ReadGeneralRegisters (
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINTN i;
+ CHAR8 OutBuffer[385]; // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
+ CHAR8 *OutBufPtr; // pointer to the output buffer
+
+ OutBufPtr = OutBuffer;
+ for(i = 0 ; i < MaxRegisterCount() ; i++) { // there are only 24 registers to read
+ OutBufPtr = BasicReadRegister(SystemContext, i, OutBufPtr);
+ }
+
+ *OutBufPtr = '\0'; // the end of the buffer
+ SendPacket (OutBuffer);
+}
+
+
+/**
+ Adds the RegNumber-th register's value to the output buffer, starting at the given OutBufPtr
+
+ @param SystemContext Register content at time of the exception
+ @param RegNumber the number of the register that we want to write
+ @param InBufPtr pointer to the output buffer. the new data will be extracted from the input buffer from this point on.
+ @retval the pointer to the next character of the input buffer that can be used
+ **/
+CHAR8 *
+BasicWriteRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN RegNumber,
+ IN CHAR8 *InBufPtr
+ )
+{
+ UINTN RegSize;
+ UINTN TempValue; // the value transferred from a hex char
+ UINT64 NewValue; // the new value of the RegNumber-th Register
+
+ NewValue = 0;
+ RegSize = 0;
+ while (RegSize < 64) {
+ TempValue = HexCharToInt(*InBufPtr++);
+
+ if (TempValue < 0) {
+ SendError (GDB_EBADMEMDATA);
+ return NULL;
+ }
+
+ NewValue += (TempValue << (RegSize+4));
+ TempValue = HexCharToInt(*InBufPtr++);
+
+ if (TempValue < 0) {
+ SendError (GDB_EBADMEMDATA);
+ return NULL;
+ }
+
+ NewValue += (TempValue << RegSize);
+ RegSize = RegSize + 8;
+ }
+ *(FindPointerToRegister(SystemContext, RegNumber)) = NewValue;
+ return InBufPtr;
+}
+
+
+/** ‘P n...=r...’
+ Writes the new value of n-th register received into the input buffer to the n-th register
+
+ @param SystemContext Register content at time of the exception
+ @param InBuffer Ponter to the input buffer received from gdb server
+ **/
+VOID
+EFIAPI
+WriteNthRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *InBuffer
+ )
+{
+ UINTN RegNumber;
+ CHAR8 RegNumBuffer[MAX_REG_NUM_BUF_SIZE]; // put the 'n..' part of the message into this array
+ CHAR8 *RegNumBufPtr;
+ CHAR8 *InBufPtr; // pointer to the input buffer
+
+ // find the register number to write
+ InBufPtr = &InBuffer[1];
+ RegNumBufPtr = RegNumBuffer;
+ while (*InBufPtr != '=') {
+ *RegNumBufPtr++ = *InBufPtr++;
+ }
+ *RegNumBufPtr = '\0';
+ RegNumber = AsciiStrHexToUintn (RegNumBuffer);
+
+ // check if this is a valid Register Number
+ if ((RegNumber < 0) || (RegNumber >= MaxRegisterCount())) {
+ SendError (GDB_EINVALIDREGNUM);
+ return;
+ }
+ InBufPtr++; // skips the '=' character
+ BasicWriteRegister (SystemContext, RegNumber, InBufPtr);
+ SendSuccess();
+}
+
+
+/** ‘G XX...’
+ Writes the new values received into the input buffer to the general registers
+
+ @param SystemContext Register content at time of the exception
+ @param InBuffer Pointer to the input buffer received from gdb server
+ **/
+VOID
+EFIAPI
+WriteGeneralRegisters (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *InBuffer
+ )
+{
+ UINTN i;
+ CHAR8 *InBufPtr; /// pointer to the input buffer
+
+ // check to see if the buffer is the right size which is
+ // 1 (for 'G') + 16 (for 16 registers) * 8 ( for 8 hex chars each) = 385
+ if (AsciiStrLen(InBuffer) != 385) { // 24 regs, 16 hex chars each, and the end '\0' (escape seq)
+ //Bad message. Message is not the right length
+ SendError (GDB_EBADBUFSIZE);
+ return;
+ }
+
+ InBufPtr = &InBuffer[1];
+
+ // Read the new values for the registers from the input buffer to an array, NewValueArray.
+ // The values in the array are in the gdb ordering
+ for(i=0; i < MaxRegisterCount(); i++) { // there are only 16 registers to write
+ InBufPtr = BasicWriteRegister(SystemContext, i, InBufPtr);
+ }
+
+ SendSuccess();
+}
+
+
+ /**
+ Insert Single Step in the SystemContext
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+AddSingleStep (
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ SystemContext.SystemContextX64->Rflags |= TF_BIT; //Setting the TF bit.
+}
+
+
+
+/**
+ Remove Single Step in the SystemContext
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+RemoveSingleStep (
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ SystemContext.SystemContextX64->Rflags &= ~TF_BIT; // clearing the TF bit.
+}
+
+
+
+/** ‘c [addr ]’
+ Continue. addr is Address to resume. If addr is omitted, resume at current
+ Address.
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+EFIAPI
+ContinueAtAddress (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ if (PacketData[1] != '\0') {
+ SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn(&PacketData[1]);
+ }
+}
+
+
+/** ‘s [addr ]’
+ Single step. addr is the Address at which to resume. If addr is omitted, resume
+ at same Address.
+
+ @param SystemContext Register content at time of the exception
+ **/
+VOID
+EFIAPI
+SingleStep (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ if (PacketData[1] != '\0') {
+ SystemContext.SystemContextX64->Rip = AsciiStrHexToUintn (&PacketData[1]);
+ }
+
+ AddSingleStep (SystemContext);
+}
+
+
+/**
+ Returns breakpoint data address from DR0-DR3 based on the input breakpoint
+ number
+
+ @param SystemContext Register content at time of the exception
+ @param BreakpointNumber Breakpoint number
+
+ @retval Address Data address from DR0-DR3 based on the
+ breakpoint number.
+
+**/
+UINTN
+GetBreakpointDataAddress (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN BreakpointNumber
+ )
+{
+ UINTN Address;
+
+ if (BreakpointNumber == 1) {
+ Address = SystemContext.SystemContextIa32->Dr0;
+ } else if (BreakpointNumber == 2) {
+ Address = SystemContext.SystemContextIa32->Dr1;
+ } else if (BreakpointNumber == 3) {
+ Address = SystemContext.SystemContextIa32->Dr2;
+ } else if (BreakpointNumber == 4) {
+ Address = SystemContext.SystemContextIa32->Dr3;
+ } else {
+ Address = 0;
+ }
+
+ return Address;
+}
+
+/**
+ Returns currently detected breakpoint value based on the register
+ DR6 B0-B3 field.
+ If no breakpoint is detected then it returns 0.
+
+ @param SystemContext Register content at time of the exception
+
+ @retval {1-4} Currently detected breakpoint value
+ @retval 0 No breakpoint detected.
+
+**/
+UINTN
+GetBreakpointDetected (
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ IA32_DR6 Dr6;
+ UINTN BreakpointNumber;
+
+ Dr6.UintN = SystemContext.SystemContextIa32->Dr6;
+
+ if (Dr6.Bits.B0 == 1) {
+ BreakpointNumber = 1;
+ } else if (Dr6.Bits.B1 == 1) {
+ BreakpointNumber = 2;
+ } else if (Dr6.Bits.B2 == 1) {
+ BreakpointNumber = 3;
+ } else if (Dr6.Bits.B3 == 1) {
+ BreakpointNumber = 4;
+ } else {
+ BreakpointNumber = 0; //No breakpoint detected
+ }
+
+ return BreakpointNumber;
+}
+
+/**
+ Returns Breakpoint type (InstructionExecution, DataWrite, DataRead
+ or DataReadWrite) based on the Breakpoint number
+
+ @param SystemContext Register content at time of the exception
+ @param BreakpointNumber Breakpoint number
+
+ @retval BREAK_TYPE Breakpoint type value read from register DR7 RWn
+ field. For unknown value, it returns NotSupported.
+
+**/
+BREAK_TYPE
+GetBreakpointType (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN BreakpointNumber
+ )
+{
+ IA32_DR7 Dr7;
+ BREAK_TYPE Type = NotSupported; //Default is NotSupported type
+
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
+
+ if (BreakpointNumber == 1) {
+ Type = (BREAK_TYPE) Dr7.Bits.RW0;
+ } else if (BreakpointNumber == 2) {
+ Type = (BREAK_TYPE) Dr7.Bits.RW1;
+ } else if (BreakpointNumber == 3) {
+ Type = (BREAK_TYPE) Dr7.Bits.RW2;
+ } else if (BreakpointNumber == 4) {
+ Type = (BREAK_TYPE) Dr7.Bits.RW3;
+ }
+
+ return Type;
+}
+
+
+/**
+ Parses Length and returns the length which DR7 LENn field accepts.
+ For example: If we receive 1-Byte length then we should return 0.
+ Zero gets written to DR7 LENn field.
+
+ @param Length Breakpoint length in Bytes (1 byte, 2 byte, 4 byte)
+
+ @retval Length Appropriate converted values which DR7 LENn field accepts.
+
+**/
+UINTN
+ConvertLengthData (
+ IN UINTN Length
+ )
+{
+ if (Length == 1) { //1-Byte length
+ return 0;
+ } else if (Length == 2) { //2-Byte length
+ return 1;
+ } else if (Length == 4) { //4-Byte length
+ return 3;
+ } else { //Undefined or 8-byte length
+ return 2;
+ }
+}
+
+
+/**
+ Finds the next free debug register. If all the registers are occupied then
+ EFI_OUT_OF_RESOURCES is returned.
+
+ @param SystemContext Register content at time of the exception
+ @param Register Register value (0 - 3 for the first free debug register)
+
+ @retval EFI_STATUS Appropriate status value.
+
+**/
+EFI_STATUS
+FindNextFreeDebugRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ OUT UINTN *Register
+ )
+{
+ IA32_DR7 Dr7;
+
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
+
+ if (Dr7.Bits.G0 == 0) {
+ *Register = 0;
+ } else if (Dr7.Bits.G1 == 0) {
+ *Register = 1;
+ } else if (Dr7.Bits.G2 == 0) {
+ *Register = 2;
+ } else if (Dr7.Bits.G3 == 0) {
+ *Register = 3;
+ } else {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Enables the debug register. Writes Address value to appropriate DR0-3 register.
+ Sets LENn, Gn, RWn bits in DR7 register.
+
+ @param SystemContext Register content at time of the exception
+ @param Register Register value (0 - 3)
+ @param Address Breakpoint address value
+ @param Type Breakpoint type (Instruction, Data write,
+ Data read or write etc.)
+
+ @retval EFI_STATUS Appropriate status value.
+
+**/
+EFI_STATUS
+EnableDebugRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN Register,
+ IN UINTN Address,
+ IN UINTN Length,
+ IN UINTN Type
+ )
+{
+ IA32_DR7 Dr7;
+
+ //Convert length data
+ Length = ConvertLengthData (Length);
+
+ //For Instruction execution, length should be 0
+ //(Ref. Intel reference manual 18.2.4)
+ if ((Type == 0) && (Length != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
+ //software breakpoint. We should send empty packet in both these cases.
+ if ((Type == (BREAK_TYPE)DataRead) ||
+ (Type == (BREAK_TYPE)SoftwareBreakpoint)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //Read DR7 so appropriate Gn, RWn and LENn bits can be modified.
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
+
+ if (Register == 0) {
+ SystemContext.SystemContextIa32->Dr0 = Address;
+ Dr7.Bits.G0 = 1;
+ Dr7.Bits.RW0 = Type;
+ Dr7.Bits.LEN0 = Length;
+ } else if (Register == 1) {
+ SystemContext.SystemContextIa32->Dr1 = Address;
+ Dr7.Bits.G1 = 1;
+ Dr7.Bits.RW1 = Type;
+ Dr7.Bits.LEN1 = Length;
+ } else if (Register == 2) {
+ SystemContext.SystemContextIa32->Dr2 = Address;
+ Dr7.Bits.G2 = 1;
+ Dr7.Bits.RW2 = Type;
+ Dr7.Bits.LEN2 = Length;
+ } else if (Register == 3) {
+ SystemContext.SystemContextIa32->Dr3 = Address;
+ Dr7.Bits.G3 = 1;
+ Dr7.Bits.RW3 = Type;
+ Dr7.Bits.LEN3 = Length;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //Update Dr7 with appropriate Gn, RWn and LENn bits
+ SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Returns register number 0 - 3 for the maching debug register.
+ This function compares incoming Address, Type, Length and
+ if there is a match then it returns the appropriate register number.
+ In case of mismatch, function returns EFI_NOT_FOUND message.
+
+ @param SystemContext Register content at time of the exception
+ @param Address Breakpoint address value
+ @param Length Breakpoint length value
+ @param Type Breakpoint type (Instruction, Data write, Data read
+ or write etc.)
+ @param Register Register value to be returned
+
+ @retval EFI_STATUS Appropriate status value.
+
+**/
+EFI_STATUS
+FindMatchingDebugRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN Address,
+ IN UINTN Length,
+ IN UINTN Type,
+ OUT UINTN *Register
+ )
+{
+ IA32_DR7 Dr7;
+
+ //Hardware doesn't support ReadWatch (z3 packet) type. GDB can handle
+ //software breakpoint. We should send empty packet in both these cases.
+ if ((Type == (BREAK_TYPE)DataRead) ||
+ (Type == (BREAK_TYPE)SoftwareBreakpoint)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //Convert length data
+ Length = ConvertLengthData(Length);
+
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
+
+ if ((Dr7.Bits.G0 == 1) &&
+ (Dr7.Bits.LEN0 == Length) &&
+ (Dr7.Bits.RW0 == Type) &&
+ (Address == SystemContext.SystemContextIa32->Dr0)) {
+ *Register = 0;
+ } else if ((Dr7.Bits.G1 == 1) &&
+ (Dr7.Bits.LEN1 == Length) &&
+ (Dr7.Bits.RW1 == Type) &&
+ (Address == SystemContext.SystemContextIa32->Dr1)) {
+ *Register = 1;
+ } else if ((Dr7.Bits.G2 == 1) &&
+ (Dr7.Bits.LEN2 == Length) &&
+ (Dr7.Bits.RW2 == Type) &&
+ (Address == SystemContext.SystemContextIa32->Dr2)) {
+ *Register = 2;
+ } else if ((Dr7.Bits.G3 == 1) &&
+ (Dr7.Bits.LEN3 == Length) &&
+ (Dr7.Bits.RW3 == Type) &&
+ (Address == SystemContext.SystemContextIa32->Dr3)) {
+ *Register = 3;
+ } else {
+ Print ((CHAR16 *)L"No match found..\n");
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Disables the particular debug register.
+
+ @param SystemContext Register content at time of the exception
+ @param Register Register to be disabled
+
+ @retval EFI_STATUS Appropriate status value.
+
+**/
+EFI_STATUS
+DisableDebugRegister (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN UINTN Register
+ )
+{
+ IA32_DR7 Dr7;
+ UINTN Address = 0;
+
+ //Read DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
+ Dr7.UintN = SystemContext.SystemContextIa32->Dr7;
+
+ if (Register == 0) {
+ SystemContext.SystemContextIa32->Dr0 = Address;
+ Dr7.Bits.G0 = 0;
+ Dr7.Bits.RW0 = 0;
+ Dr7.Bits.LEN0 = 0;
+ } else if (Register == 1) {
+ SystemContext.SystemContextIa32->Dr1 = Address;
+ Dr7.Bits.G1 = 0;
+ Dr7.Bits.RW1 = 0;
+ Dr7.Bits.LEN1 = 0;
+ } else if (Register == 2) {
+ SystemContext.SystemContextIa32->Dr2 = Address;
+ Dr7.Bits.G2 = 0;
+ Dr7.Bits.RW2 = 0;
+ Dr7.Bits.LEN2 = 0;
+ } else if (Register == 3) {
+ SystemContext.SystemContextIa32->Dr3 = Address;
+ Dr7.Bits.G3 = 0;
+ Dr7.Bits.RW3 = 0;
+ Dr7.Bits.LEN3 = 0;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //Update DR7 register so appropriate Gn, RWn and LENn bits can be turned off.
+ SystemContext.SystemContextIa32->Dr7 = Dr7.UintN;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ ‘Z1, [addr], [length]’
+ ‘Z2, [addr], [length]’
+ ‘Z3, [addr], [length]’
+ ‘Z4, [addr], [length]’
+
+ Insert hardware breakpoint/watchpoint at address addr of size length
+
+ @param SystemContext Register content at time of the exception
+ @param *PacketData Pointer to the Payload data for the packet
+
+**/
+VOID
+EFIAPI
+InsertBreakPoint (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ UINTN Type;
+ UINTN Address;
+ UINTN Length;
+ UINTN Register;
+ EFI_STATUS Status;
+ BREAK_TYPE BreakType = NotSupported;
+ UINTN ErrorCode;
+
+ ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
+ if (ErrorCode > 0) {
+ SendError ((UINT8)ErrorCode);
+ return;
+ }
+
+ switch (Type) {
+
+ case 0: //Software breakpoint
+ BreakType = SoftwareBreakpoint;
+ break;
+
+ case 1: //Hardware breakpoint
+ BreakType = InstructionExecution;
+ break;
+
+ case 2: //Write watchpoint
+ BreakType = DataWrite;
+ break;
+
+ case 3: //Read watchpoint
+ BreakType = DataRead;
+ break;
+
+ case 4: //Access watchpoint
+ BreakType = DataReadWrite;
+ break;
+
+ default :
+ Print ((CHAR16 *)L"Insert breakpoint default: %x\n", Type);
+ SendError (GDB_EINVALIDBRKPOINTTYPE);
+ return;
+ }
+
+ // Find next free debug register
+ Status = FindNextFreeDebugRegister (SystemContext, &Register);
+ if (EFI_ERROR(Status)) {
+ Print ((CHAR16 *)L"No space left on device\n");
+ SendError (GDB_ENOSPACE);
+ return;
+ }
+
+ // Write Address, length data at particular DR register
+ Status = EnableDebugRegister (SystemContext, Register, Address, Length, (UINTN)BreakType);
+ if (EFI_ERROR(Status)) {
+
+ if (Status == EFI_UNSUPPORTED) {
+ Print ((CHAR16 *)L"Not supported\n");
+ SendNotSupported();
+ return;
+ }
+
+ Print ((CHAR16 *)L"Invalid argument\n");
+ SendError (GDB_EINVALIDARG);
+ return;
+ }
+
+ SendSuccess ();
+}
+
+
+/**
+ ‘z1, [addr], [length]’
+ ‘z2, [addr], [length]’
+ ‘z3, [addr], [length]’
+ ‘z4, [addr], [length]’
+
+ Remove hardware breakpoint/watchpoint at address addr of size length
+
+ @param *PacketData Pointer to the Payload data for the packet
+
+**/
+VOID
+EFIAPI
+RemoveBreakPoint (
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN CHAR8 *PacketData
+ )
+{
+ UINTN Type;
+ UINTN Address;
+ UINTN Length;
+ UINTN Register;
+ BREAK_TYPE BreakType = NotSupported;
+ EFI_STATUS Status;
+ UINTN ErrorCode;
+
+ //Parse breakpoint packet data
+ ErrorCode = ParseBreakpointPacket (PacketData, &Type, &Address, &Length);
+ if (ErrorCode > 0) {
+ SendError ((UINT8)ErrorCode);
+ return;
+ }
+
+ switch (Type) {
+
+ case 0: //Software breakpoint
+ BreakType = SoftwareBreakpoint;
+ break;
+
+ case 1: //Hardware breakpoint
+ BreakType = InstructionExecution;
+ break;
+
+ case 2: //Write watchpoint
+ BreakType = DataWrite;
+ break;
+
+ case 3: //Read watchpoint
+ BreakType = DataRead;
+ break;
+
+ case 4: //Access watchpoint
+ BreakType = DataReadWrite;
+ break;
+
+ default :
+ SendError (GDB_EINVALIDBRKPOINTTYPE);
+ return;
+ }
+
+ //Find matching debug register
+ Status = FindMatchingDebugRegister (SystemContext, Address, Length, (UINTN)BreakType, &Register);
+ if (EFI_ERROR(Status)) {
+
+ if (Status == EFI_UNSUPPORTED) {
+ Print ((CHAR16 *)L"Not supported.\n");
+ SendNotSupported();
+ return;
+ }
+
+ Print ((CHAR16 *)L"No matching register found.\n");
+ SendError (GDB_ENOSPACE);
+ return;
+ }
+
+ //Remove breakpoint
+ Status = DisableDebugRegister(SystemContext, Register);
+ if (EFI_ERROR(Status)) {
+ Print ((CHAR16 *)L"Invalid argument.\n");
+ SendError (GDB_EINVALIDARG);
+ return;
+ }
+
+ SendSuccess ();
+}
+
+
+VOID
+InitializeProcessor (
+ VOID
+ )
+{
+}
+
+BOOLEAN
+ValidateAddress (
+ IN VOID *Address
+ )
+{
+ return TRUE;
+}
+
+BOOLEAN
+ValidateException (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ return TRUE;
+}
+
diff --git a/EmbeddedPkg/Include/Library/EblAddExternalCommandLib.h b/EmbeddedPkg/Include/Library/EblAddExternalCommandLib.h new file mode 100644 index 0000000000..c3f1678180 --- /dev/null +++ b/EmbeddedPkg/Include/Library/EblAddExternalCommandLib.h @@ -0,0 +1,122 @@ +/** @file + Include flie for basic command line parser for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation<BR> + Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EBL_ADD_EXTERNAL_COMMAND_LIB_H__ +#define __EBL_ADD_EXTERNAL_COMMAND_LIB_H__ + +#include <PiDxe.h> +#include <Protocol/EblAddCommand.h> + + +EFI_STATUS +EFIAPI +EblAddExternalCommands ( + IN const EBL_COMMAND_TABLE *EntryArray, + IN UINTN ArrayCount + ); + +/** + + Return a keypress or optionally timeout if a timeout value was passed in. + + An optional callback funciton is called evey second when waiting for a + + timeout. + + + + @param Key EFI Key information returned + + @param TimeoutInSec Number of seconds to wait to timeout + + @param CallBack Callback called every second during the timeout wait + + + + @return EFI_SUCCESS Key was returned + + @return EFI_TIMEOUT If the TimoutInSec expired + + + +**/ + +EFI_STATUS + +EFIAPI + +EblGetCharKey ( + + IN OUT EFI_INPUT_KEY *Key, + + IN UINTN TimeoutInSec, + + IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL + + ); + + + + + +/** + + This routine is used prevent command output data from scrolling off the end + + of the screen. The global gPageBreak is used to turn on or off this feature. + + If the CurrentRow is near the end of the screen pause and print out a prompt + + If the use hits Q to quit return TRUE else for any other key return FALSE. + + PrefixNewline is used to figure out if a newline is needed before the prompt + + string. This depends on the last print done before calling this function. + + CurrentRow is updated by one on a call or set back to zero if a prompt is + + needed. + + + + @param CurrentRow Used to figure out if its the end of the page and updated + + @param PrefixNewline Did previous print issue a newline + + + + @return TRUE if Q was hit to quit, FALSE in all other cases. + + + +**/ + +BOOLEAN + +EFIAPI + +EblAnyKeyToContinueQtoQuit ( + + IN UINTN *CurrentRow, + + IN BOOLEAN PrefixNewline + + ); + + + +#endif + diff --git a/EmbeddedPkg/Include/Library/EblCmdLib.h b/EmbeddedPkg/Include/Library/EblCmdLib.h new file mode 100644 index 0000000000..70ed3c8c71 --- /dev/null +++ b/EmbeddedPkg/Include/Library/EblCmdLib.h @@ -0,0 +1,48 @@ +/** @file + Include flie for basic command line parser for EBL (Embedded Boot Loader) + + Copyright (c) 2007, Intel Corporation<BR> + Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EBL_LIB_H__ +#define __EBL_LIB_H__ + +#include <PiDxe.h> +#include <Protocol/EblAddCommand.h> + + +VOID +EblAddCommand ( + IN const EBL_COMMAND_TABLE *Entry + ); + +VOID +EblAddCommands ( + IN const EBL_COMMAND_TABLE *EntryArray, + IN UINTN ArrayCount + ); + + +// +// LIbrary constructor called directly from Ebl Code. +// This module calls EblAddCommand () or EblAddCommands () to register new commands +// +VOID +EblInitializeExternalCmd ( + VOID + ); + + + +#endif + diff --git a/EmbeddedPkg/Include/Library/EblNetworkLib.h b/EmbeddedPkg/Include/Library/EblNetworkLib.h new file mode 100644 index 0000000000..5c9ec03cfc --- /dev/null +++ b/EmbeddedPkg/Include/Library/EblNetworkLib.h @@ -0,0 +1,68 @@ +/** @file + Abstractions for Ebl network accesses. + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EBL_NETWORK_LIB_H__ +#define __EBL_NETWORK_LIB_H__ + +#include <Protocol/PxeBaseCode.h> + + +EFI_STATUS +EFIAPI +EblGetCurrentIpAddress ( + IN OUT EFI_IP_ADDRESS *Ip + ); + +EFI_STATUS +EFIAPI +EblGetCurrentMacAddress ( + IN OUT EFI_MAC_ADDRESS *Mac + ); + +CHAR8 * +EFIAPI +EblLoadFileBootTypeString ( + IN EFI_HANDLE Handle + ); + +EFI_STATUS +EFIAPI +EblPerformDHCP ( + IN BOOLEAN SortOffers + ); + +EFI_STATUS +EFIAPI +EblSetStationIp ( + IN EFI_IP_ADDRESS *NewStationIp, OPTIONAL + IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL + ); + +EFI_STATUS +EFIAPI +EblMtftp ( + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + IN OUT VOID *BufferPtr OPTIONAL, + IN BOOLEAN Overwrite, + IN OUT UINT64 *BufferSize, + IN UINTN *BlockSize OPTIONAL, + IN EFI_IP_ADDRESS *ServerIp, + IN UINT8 *Filename OPTIONAL, + IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL, + IN BOOLEAN DontUseBuffer + ); + +#endif + diff --git a/EmbeddedPkg/Include/Library/EfiFileLib.h b/EmbeddedPkg/Include/Library/EfiFileLib.h new file mode 100644 index 0000000000..992d326997 --- /dev/null +++ b/EmbeddedPkg/Include/Library/EfiFileLib.h @@ -0,0 +1,315 @@ +/** @file
+ Library functions that perform file IO. Memory buffer, file system, and
+ fimrware volume operations are supproted.
+
+ Copyright (c) 2007, Intel Corporation<BR>
+ Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Basic support for opening files on different device types. The device string
+ is in the form of DevType:Path. Current DevType is required as there is no
+ current mounted device concept of current working directory concept implement
+ by this library.
+
+ Device names are case insensative and only check the leading characters for
+ unique matches. Thus the following are all the same:
+ LoadFile0:
+ l0:
+ L0:
+ Lo0:
+
+ Supported Device Names:
+ A0x1234:0x12 - A memory buffer starting at address 0x1234 for 0x12 bytes
+ l1: - EFI LoadFile device one.
+ B0: - EFI BlockIo zero.
+ fs3: - EFI Simple File System device 3
+ Fv2: - EFI Firmware VOlume device 2
+ 1.2.3.4:name - TFTP IP and file name
+
+**/
+
+#ifndef __EFI_FILE_LIB_H__
+#define __EFI_FILE_LIB_H__
+
+#include <PiDxe.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/FirmwareVolumeBlock.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+
+#define MAX_PATHNAME 0x200
+
+/// Type of the file that has been opened
+typedef enum {
+ EfiOpenLoadFile,
+ EfiOpenMemoryBuffer,
+ EfiOpenFirmwareVolume,
+ EfiOpenFileSystem,
+ EfiOpenBlockIo,
+ EfiOpenTftp,
+ EfiOpenMaxValue
+} EFI_OPEN_FILE_TYPE;
+
+
+/// Public information about the open file
+typedef struct {
+ UINTN Version; // Common information
+ EFI_OPEN_FILE_TYPE Type;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS LastError;
+ EFI_HANDLE EfiHandle;
+ CHAR8 *DeviceName;
+ CHAR8 *FileName;
+
+ UINT64 CurrentPosition; // Information for Seek
+ UINT64 MaxPosition;
+
+ UINTN BaseOffset; // Base offset for hexdump command
+
+ UINTN Size; // Valid for all types other than l#:
+ UINT8 *Buffer; // Information valid for A#:
+
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; // Information valid for Fv#:
+ EFI_GUID FvNameGuid;
+ EFI_SECTION_TYPE FvSectionType;
+ EFI_FV_FILETYPE FvType;
+ EFI_FV_FILE_ATTRIBUTES FvAttributes;
+
+ EFI_PHYSICAL_ADDRESS FvStart;
+ UINTN FvSize;
+
+ EFI_FILE *FsFileHandle; // Information valid for Fs#:
+ EFI_FILE_SYSTEM_INFO *FsInfo;
+ EFI_FILE_INFO *FsFileInfo;
+ EFI_BLOCK_IO_MEDIA FsBlockIoMedia; // Information valid for Fs#: or B#:
+
+ UINTN DiskOffset; // Information valid for B#:
+
+ EFI_LOAD_FILE_PROTOCOL *LoadFile; // Information valid for l#:
+
+ EFI_IP_ADDRESS ServerIp; // Information valid for t:
+ BOOLEAN IsDirty;
+ BOOLEAN IsBufferValid;
+
+} EFI_OPEN_FILE;
+
+
+/// Type of Seek to perform
+typedef enum {
+ EfiSeekStart,
+ EfiSeekCurrent,
+ EfiSeekEnd,
+ EfiSeekMax
+} EFI_SEEK_TYPE;
+
+
+/**
+ Open a device named by PathName. The PathName includes a device name and
+ path seperated by a :. See file header for more details on the PathName
+ syntax. There is no checking to prevent a file from being opened more than
+ one type.
+
+ SectionType is only used to open an FV. Each file in an FV contains multiple
+ secitons and only the SectionType section is opened.
+
+ For any file that is opened with EfiOpen() must be closed with EfiClose().
+
+ @param PathName Path to parse to open
+ @param OpenMode Same as EFI_FILE.Open()
+ @param SectionType Section in FV to open.
+
+ @return NULL Open failed
+ @return Valid EFI_OPEN_FILE handle
+
+**/
+EFI_OPEN_FILE *
+EfiOpen (
+ IN CHAR8 *PathName,
+ IN CONST UINT64 OpenMode,
+ IN CONST EFI_SECTION_TYPE SectionType
+ );
+
+EFI_STATUS
+EfiCopyFile (
+ IN CHAR8 *DestinationFile,
+ IN CHAR8 *SourceFile
+ );
+
+/**
+ Use DeviceType and Index to form a valid PathName and try and open it.
+
+ @param DeviceType Device type to open
+ @param Index Device Index to use. Zero relative.
+
+ @return NULL Open failed
+ @return Valid EFI_OPEN_FILE handle
+
+**/
+EFI_OPEN_FILE *
+EfiDeviceOpenByType (
+ IN EFI_OPEN_FILE_TYPE DeviceType,
+ IN UINTN Index
+ );
+
+
+/**
+ Close a file handle opened by EfiOpen() and free all resources allocated by
+ EfiOpen().
+
+ @param Stream Open File Handle
+
+ @return EFI_INVALID_PARAMETER Stream is not an Open File
+ @return EFI_SUCCESS Steam closed
+
+**/
+EFI_STATUS
+EfiClose (
+ IN EFI_OPEN_FILE *Stream
+ );
+
+
+/**
+ Return the size of the file represented by Stream. Also return the current
+ Seek position. Opening a file will enable a valid file size to be returned.
+ LoadFile is an exception as a load file size is set to zero.
+
+ @param Stream Open File Handle
+
+ @return 0 Stream is not an Open File or a valid LoadFile handle
+
+**/
+UINTN
+EfiTell (
+ IN EFI_OPEN_FILE *Stream,
+ OUT UINT64 *CurrentPosition OPTIONAL
+ );
+
+
+/**
+ Seek to the Offset locaiton in the file. LoadFile and FV device types do
+ not support EfiSeek(). It is not possible to grow the file size using
+ EfiSeek().
+
+ SeekType defines how use Offset to calculate the new file position:
+ EfiSeekStart : Position = Offset
+ EfiSeekCurrent: Position is Offset bytes from the current position
+ EfiSeekEnd : Only supported if Offset is zero to seek to end of file.
+
+ @param Stream Open File Handle
+ @param Offset Offset to seek too.
+ @param SeekType Type of seek to perform
+
+
+ @return EFI_INVALID_PARAMETER Stream is not an Open File
+ @return EFI_UNSUPPORTED LoadFile and FV doe not support Seek
+ @return EFI_NOT_FOUND Seek past the end of the file.
+ @return EFI_SUCCESS Steam closed
+
+**/
+EFI_STATUS
+EfiSeek (
+ IN EFI_OPEN_FILE *Stream,
+ IN EFI_LBA Offset,
+ IN EFI_SEEK_TYPE SeekType
+ );
+
+
+/**
+ Read BufferSize bytes from the current locaiton in the file. For load file
+ and FV case you must read the entire file.
+
+ @param Stream Open File Handle
+ @param Buffer Caller allocated buffer.
+ @param BufferSize Size of buffer in bytes.
+
+
+ @return EFI_SUCCESS Stream is not an Open File
+ @return EFI_END_OF_FILE Tried to read past the end of the file
+ @return EFI_INVALID_PARAMETER Stream is not an open file handle
+ @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read
+ @return "other" Error returned from device read
+
+**/
+EFI_STATUS
+EfiRead (
+ IN EFI_OPEN_FILE *Stream,
+ OUT VOID *Buffer,
+ OUT UINTN *BufferSize
+ );
+
+
+/**
+ Read the entire file into a buffer. This routine allocates the buffer and
+ returns it to the user full of the read data.
+
+ This is very useful for load flie where it's hard to know how big the buffer
+ must be.
+
+ @param Stream Open File Handle
+ @param Buffer Pointer to buffer to return.
+ @param BufferSize Pointer to Size of buffer return..
+
+
+ @return EFI_SUCCESS Stream is not an Open File
+ @return EFI_END_OF_FILE Tried to read past the end of the file
+ @return EFI_INVALID_PARAMETER Stream is not an open file handle
+ @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read
+ @return "other" Error returned from device read
+
+**/
+EFI_STATUS
+EfiReadAllocatePool (
+ IN EFI_OPEN_FILE *Stream,
+ OUT VOID **Buffer,
+ OUT UINTN *BufferSize
+ );
+
+
+/**
+ Write data back to the file.
+
+ @param Stream Open File Handle
+ @param Buffer Pointer to buffer to return.
+ @param BufferSize Pointer to Size of buffer return..
+
+
+ @return EFI_SUCCESS Stream is not an Open File
+ @return EFI_END_OF_FILE Tried to read past the end of the file
+ @return EFI_INVALID_PARAMETER Stream is not an open file handle
+ @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read
+ @return "other" Error returned from device write
+
+**/
+EFI_STATUS
+EfiWrite (
+ IN EFI_OPEN_FILE *Stream,
+ OUT VOID *Buffer,
+ OUT UINTN *BufferSize
+ );
+
+
+/**
+ Return the number of devices of the current type active in the system
+
+ @param Type Device type to check
+
+ @return 0 Invalid type
+
+**/
+UINTN
+EfiGetDeviceCounts (
+ IN EFI_OPEN_FILE_TYPE Type
+ );
+
+#endif
diff --git a/EmbeddedPkg/Include/Library/EfiResetSystemLib.h b/EmbeddedPkg/Include/Library/EfiResetSystemLib.h new file mode 100644 index 0000000000..162857660f --- /dev/null +++ b/EmbeddedPkg/Include/Library/EfiResetSystemLib.h @@ -0,0 +1,58 @@ +/** @file
+
+ Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __EFI_RESET_SYSTEM_LIB_H___
+#define __EFI_RESET_SYSTEM_LIB_H___
+
+
+/**
+ Resets the entire platform.
+
+ @param ResetType The type of reset to perform.
+ @param ResetStatus The status code for the reset.
+ @param DataSize The size, in bytes, of WatchdogData.
+ @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
+ EfiResetShutdown the data buffer starts with a Null-terminated
+ Unicode string, optionally followed by additional binary data.
+
+**/
+EFI_STATUS
+EFIAPI
+LibResetSystem (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN CHAR16 *ResetData OPTIONAL
+ );
+
+
+
+/**
+ Initialize any infrastructure required for LibResetSystem () to function.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+LibInitializeResetSystem (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
diff --git a/EmbeddedPkg/Include/Library/GdbSerialLib.h b/EmbeddedPkg/Include/Library/GdbSerialLib.h new file mode 100644 index 0000000000..3d72005c91 --- /dev/null +++ b/EmbeddedPkg/Include/Library/GdbSerialLib.h @@ -0,0 +1,107 @@ +/** @file + Basic serial IO abstaction for GDB + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __GDB_SERIAL_LIB_H__ +#define __GDB_SERIAL_LIB_H__ + + + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data buts, and stop bits on a serial device. This call is optional as the serial + port will be set up with defaults base on PCD values. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the + device's default interface speed. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + + @retval EFI_SUCCESS The device was configured. + @retval EFI_DEVICE_ERROR The serial device could not be coonfigured. + +**/ +RETURN_STATUS +EFIAPI +GdbSerialInit ( + IN UINT64 BaudRate, + IN UINT8 Parity, + IN UINT8 DataBits, + IN UINT8 StopBits + ); + + +/** + Check to see if a character is available from GDB. Do not read the character as that is + done via GdbGetChar(). + + @return TRUE - Character availible + @return FALSE - Character not availible + +**/ +BOOLEAN +EFIAPI +GdbIsCharAvailable ( + VOID + ); + +/** + Get a character from GDB. This function must be able to run in interrupt context. + + @return A character from GDB + +**/ +CHAR8 +EFIAPI +GdbGetChar ( + VOID + ); + + +/** + Send a character to GDB. This function must be able to run in interrupt context. + + + @param Char Send a character to GDB + +**/ + +VOID +EFIAPI +GdbPutChar ( + IN CHAR8 Char + ); + + +/** + Send an ASCII string to GDB. This function must be able to run in interrupt context. + + + @param String Send a string to GDB + +**/ + +VOID +GdbPutString ( + IN CHAR8 *String + ); + + +#endif + diff --git a/EmbeddedPkg/Include/Library/HalRuntimeServicesLib.h b/EmbeddedPkg/Include/Library/HalRuntimeServicesLib.h new file mode 100644 index 0000000000..d77edfa437 --- /dev/null +++ b/EmbeddedPkg/Include/Library/HalRuntimeServicesLib.h @@ -0,0 +1,165 @@ +/** @file
+
+ Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __RUNTIME_SERVICES_LIB_H__
+#define __RUNTIME_SERVICES_LIB_H__
+
+VOID
+LibMtcInitialize (VOID);
+
+VOID
+LibMtcVirtualAddressChangeEvent (VOID);
+
+EFI_STATUS
+EFIAPI
+LibMtcGetNextHighMonotonicCount (
+ OUT UINT32 *HighCount
+ );
+
+EFI_STATUS
+LibMtcGetNextMonotonicCount (
+ OUT UINT64 *Count
+ );
+
+
+
+VOID
+LibVariableInitialize (VOID);
+
+VOID
+LibVariableVirtualAddressChangeEvent (VOID);
+
+EFI_STATUS
+LibGetVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ OUT UINT32 *Attributes OPTIONAL,
+ IN OUT UINTN *DataSize,
+ OUT VOID *Data
+ );
+
+EFI_STATUS
+LibGetNextVariableName (
+ IN OUT UINTN *VariableNameSize,
+ IN OUT CHAR16 *VariableName,
+ IN OUT EFI_GUID *VendorGuid
+ );
+
+EFI_STATUS
+LibSetVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+EFI_STATUS
+LibQueryVariableInfo (
+ IN UINT32 Attributes,
+ OUT UINT64 *MaximumVariableStorageSize,
+ OUT UINT64 *RemainingVariableStorageSize,
+ OUT UINT64 *MaximumVariableSize
+ );
+
+
+
+VOID
+LibResetInitializeReset (VOID);
+
+VOID
+LibResetVirtualAddressChangeEvent (VOID);
+
+VOID
+LibResetSystem (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN CHAR16 *ResetData OPTIONAL
+ );
+
+
+VOID
+LibCapsuleInitialize (VOID);
+
+VOID
+LibCapsuleVirtualAddressChangeEvent (VOID);
+
+EFI_STATUS
+LibUpdateCapsule (
+ IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL
+ );
+
+EFI_STATUS
+QueryCapsuleCapabilities (
+ IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray,
+ IN UINTN CapsuleCount,
+ OUT UINT64 *MaxiumCapsuleSize,
+ OUT EFI_RESET_TYPE *ResetType
+ );
+
+
+
+VOID
+LibRtcInitialize (VOID);
+
+VOID
+LibRtcVirtualAddressChangeEvent (VOID);
+
+EFI_STATUS
+LibGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ );
+
+EFI_STATUS
+LibSetTime (
+ IN EFI_TIME *Time
+ );
+
+EFI_STATUS
+LibGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ );
+
+EFI_STATUS
+LibSetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ );
+
+
+VOID
+LibReportStatusCodeInitialize (VOID);
+
+VOID
+LibReportStatusCodeVirtualAddressChangeEvent (VOID);
+
+EFI_STATUS
+LibReportStatusCode (
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value,
+ IN UINT32 Instance,
+ IN EFI_GUID *CallerId,
+ IN EFI_STATUS_CODE_DATA *Data OPTIONAL
+ );
+
+
+#endif
+
diff --git a/EmbeddedPkg/Include/Library/PrePiLib.h b/EmbeddedPkg/Include/Library/PrePiLib.h new file mode 100644 index 0000000000..61c7e4d7ac --- /dev/null +++ b/EmbeddedPkg/Include/Library/PrePiLib.h @@ -0,0 +1,766 @@ +/** @file + Library that helps implement monolithic PEI. (SEC goes to DXE) + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __PRE_PI_LIB_H__ +#define __PRE_PI_LIB_H__ + +/** + This service enables discovery of additional firmware volumes. + + @param Instance This instance of the firmware volume to find. The value 0 is the + Boot Firmware Volume (BFV). + @param FwVolHeader Pointer to the firmware volume header of the volume to return. + + @retval EFI_SUCCESS The volume was found. + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_INVALID_PARAMETER FwVolHeader is NULL. + +**/ +EFI_STATUS +EFIAPI +FfsFindNextVolume ( + IN UINTN Instance, + IN OUT EFI_PEI_FV_HANDLE *VolumeHandle + ); + + +/** + This service enables discovery of additional firmware files. + + @param SearchType A filter to find files only of this type. + @param FwVolHeader Pointer to the firmware volume header of the volume to search. + This parameter must point to a valid FFS volume. + @param FileHeader Pointer to the current file from which to begin searching. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + +**/ +EFI_STATUS +EFIAPI +FfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_PEI_FV_HANDLE VolumeHandle, + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + + +/** + This service enables discovery sections of a given type within a valid FFS file. + + @param SearchType The value of the section type to find. + @param FfsFileHeader A pointer to the file header that contains the set of sections to + be searched. + @param SectionData A pointer to the discovered section, if successful. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +FfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_PEI_FILE_HANDLE FileHandle, + OUT VOID **SectionData + ); + + +/** + Find a file in the volume by name + + @param FileName A pointer to the name of the file to + find within the firmware volume. + + @param VolumeHandle The firmware volume to search FileHandle + Upon exit, points to the found file's + handle or NULL if it could not be found. + + @retval EFI_SUCCESS File was found. + + @retval EFI_NOT_FOUND File was not found. + + @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or + FileName was NULL. + +**/ +EFI_STATUS +EFIAPI +FfsFindByName ( + IN CONST EFI_GUID *FileName, + IN CONST EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + + +/** + Get information about the file by name. + + @param FileHandle Handle of the file. + + @param FileInfo Upon exit, points to the file's + information. + + @retval EFI_SUCCESS File information returned. + + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +FfsGetFileInfo ( + IN CONST EFI_PEI_FILE_HANDLE FileHandle, + OUT EFI_FV_FILE_INFO *FileInfo + ); + + +/** + Get Information about the volume by name + + @param VolumeHandle Handle of the volume. + + @param VolumeInfo Upon exit, points to the volume's + information. + + @retval EFI_SUCCESS File information returned. + + @retval EFI_INVALID_PARAMETER If FileHandle does not + represent a valid file. + + @retval EFI_INVALID_PARAMETER If FileInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +FfsGetVolumeInfo ( + IN EFI_PEI_FV_HANDLE VolumeHandle, + OUT EFI_FV_INFO *VolumeInfo + ); + + + +/** + Get Fv image from the FV type file, then add FV & FV2 Hob. + + @param FileHandle File handle of a Fv type file. + + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + +**/ +EFI_STATUS +EFIAPI +FfsProcessFvFile ( + IN EFI_PEI_FILE_HANDLE FvFileHandle + ); + + +/** + Search through every FV until you find a file of type FileType + + @param FileType File handle of a Fv type file. + @param Volumehandle On succes Volume Handle of the match + @param FileHandle On success File Handle of the match + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully found FileType + +**/ +EFI_STATUS +EFIAPI +FfsAnyFvFindFirstFile ( + IN EFI_FV_FILETYPE FileType, + OUT EFI_PEI_FV_HANDLE *VolumeHandle, + OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + + +/** + Get Fv image from the FV type file, then add FV & FV2 Hob. + + @param FileHandle File handle of a Fv type file. + + + @retval EFI_NOT_FOUND FV image can't be found. + @retval EFI_SUCCESS Successfully to process it. + +**/ +EFI_STATUS +EFIAPI +FfsProcessFvFile ( + IN EFI_PEI_FILE_HANDLE FvFileHandle + ); + + +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + + @retval BootMode + +**/ +EFI_BOOT_MODE +EFIAPI +GetBootMode ( + VOID + ); + + +/** + This service enables PEIMs to update the boot mode variable. + + @param BootMode The value of the boot mode to set. + + @retval EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +SetBootMode ( + IN EFI_BOOT_MODE BootMode + ); + +/** + This service enables a PEIM to ascertain the address of the list of HOBs in memory. + + @param HobList A pointer to the list of HOBs that the PEI Foundation will initialize. + + @retval EFI_SUCCESS The list was successfully returned. + @retval EFI_NOT_AVAILABLE_YET The HOB list is not yet published. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ); + + +/** + Updates the pointer to the HOB list. + + @param HobList Hob list pointer to store + +**/ +EFI_STATUS +EFIAPI +SetHobList ( + IN VOID *HobList + ); + + +/** + Retrieves the magic value from the PE/COFF header. + + @param Hdr The buffer in which to return the PE32, PE32+, or TE header. + + @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32 + @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+ + +**/ +VOID +CreateHobList ( + IN VOID *MemoryBegin, + IN UINTN MemoryLength, + IN VOID *HobBase, + IN VOID *StackBase + ); + + +/** + This service enables PEIMs to create various types of HOBs. + + @param Type The type of HOB to be installed. + @param Length The length of the HOB to be added. + + @retval !NULL The HOB was successfully created. + @retval NULL There is no additional space for HOB creation. + +**/ +VOID * +CreateHob ( + IN UINT16 HobType, + IN UINT16 HobLenght + ); + + +/** + Returns the next instance of a HOB type from the starting HOB. + + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + If HobStart is NULL, then ASSERT(). + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ); + +/** + Returns the first instance of a HOB type among the whole HOB list. + + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ); + +/** + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer + unconditionally: it returns HobStart back if HobStart itself meets the requirement; + caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart. + If Guid is NULL, then ASSERT(). + If HobStart is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ); + +/** + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE () + to extract the data section and its size info respectively. + If Guid is NULL, then ASSERT(). + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ); + + +/** + Builds a HOB for a loaded PE32 module. + + This function builds a HOB for a loaded PE32 module. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If ModuleName is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ); + +/** + Builds a HOB that describes a chunk of system memory. + + This function builds a HOB that describes a chunk of system memory. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ); + +/** + Builds a GUID HOB with a certain data length. + + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If Guid is NULL, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ); + +/** + Copies a data buffer to a newly-built HOB. + + This function builds a customized HOB tagged with a GUID for identification, + copies the input data to the HOB data field and returns the start address of the GUID HOB data. + The HOB Header and Name field is already stripped. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If Guid is NULL, then ASSERT(). + If Data is NULL and DataLength > 0, then ASSERT(). + If there is no additional space for HOB creation, then ASSERT(). + If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT(). + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ); + +/** + Builds a Firmware Volume HOB. + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Builds a Firmware Volume HOB and a resrouce descriptor hob + + This function builds a Firmware Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHobs ( + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes, + IN EFI_RESOURCE_ATTRIBUTE_TYPE *ResourceAttribute OPTIONAL + ); + + +/** + Builds a EFI_HOB_TYPE_FV2 HOB. + + This function builds a EFI_HOB_TYPE_FV2 HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + @param FvName The name of the Firmware Volume. + @param FileName The name of the file. + +**/ +VOID +EFIAPI +BuildFv2Hob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN CONST EFI_GUID *FvName, + IN CONST EFI_GUID *FileName + ); + +/** + Builds a Capsule Volume HOB. + + This function builds a Capsule Volume HOB. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Builds a HOB for the CPU. + + This function builds a HOB for the CPU. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ); + +/** + Builds a HOB for the Stack. + + This function builds a HOB for the stack. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + +/** + Update the Stack Hob if the stack has been moved + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +UpdateStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ); + + +/** + Builds a HOB for the BSP store. + + This function builds a HOB for BSP store. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ); + +/** + Builds a HOB for the memory allocation. + + This function builds a HOB for the memory allocation. + It can only be invoked during PEI phase; + for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase. + If there is no additional space for HOB creation, then ASSERT(). + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ); + + +/** + Allocates one or more 4KB pages of type EfiBootServicesData. + + Allocates the number of 4KB pages of MemoryType and returns a pointer to the + allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL + is returned. If there is not enough memory remaining to satisfy the request, then NULL is + returned. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ); + +/** + Allocates a buffer of type EfiBootServicesData. + + Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a + pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is + returned. If there is not enough memory remaining to satisfy the request, then NULL is returned. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ); + + +/** + Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment. + + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an + alignment specified by Alignment. The allocated buffer is returned. If Pages is 0, then NULL is + returned. If there is not enough memory at the specified alignment remaining to satisfy the + request, then NULL is returned. + If Alignment is not a power of two and Alignment is not zero, then ASSERT(). + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer or NULL if allocation fails. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ); + + +EFI_STATUS +EFIAPI +LoadPeCoffImage ( + IN VOID *PeCoffImage, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ); + +EFI_STATUS +EFIAPI +LoadDxeCoreFromFfsFile ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN UINTN StackSize + ); + +EFI_STATUS +EFIAPI +LoadDxeCoreFromFv ( + IN UINTN *FvInstance, OPTIONAL + IN UINTN StackSize + ); + +EFI_STATUS +EFIAPI +DecompressFirstFv ( + VOID + ); + +VOID +EFIAPI +AddDxeCoreReportStatusCodeCallback ( + VOID + ); + + +#endif diff --git a/EmbeddedPkg/Include/Library/RealTimeClockLib.h b/EmbeddedPkg/Include/Library/RealTimeClockLib.h new file mode 100644 index 0000000000..6fdc34d8b9 --- /dev/null +++ b/EmbeddedPkg/Include/Library/RealTimeClockLib.h @@ -0,0 +1,138 @@ +/** @file
+ Implement EFI RealTimeClock runtime services via Lib.
+
+ Currently this driver does not support runtime virtual calling.
+
+ Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __REAL_TIME_CLOCK_LIB__
+#define __REAL_TIME_CLOCK_LIB__
+
+
+/**
+ Returns the current time and date information, and the time-keeping capabilities
+ of the hardware platform.
+
+ @param Time A pointer to storage to receive a snapshot of the current time.
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
+ device's capabilities.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ );
+
+
+/**
+ Sets the current local time and date information.
+
+ @param Time A pointer to the current time.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetTime (
+ IN EFI_TIME *Time
+ );
+
+
+/**
+ Returns the current wakeup alarm clock setting.
+
+ @param Enabled Indicates if the alarm is currently enabled or disabled.
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.
+ @param Time The current alarm setting.
+
+ @retval EFI_SUCCESS The alarm settings were returned.
+ @retval EFI_INVALID_PARAMETER Any parameter is NULL.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+LibGetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ );
+
+
+/**
+ Sets the system wakeup alarm clock time.
+
+ @param Enabled Enable or disable the wakeup alarm.
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.
+
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
+ Enable is FALSE, then the wakeup alarm was disabled.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+LibSetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ );
+
+
+
+/**
+ This is the declaration of an EFI image entry point. This can be the entry point to an application
+ written to this specification, an EFI boot service driver, or an EFI runtime driver.
+
+ @param ImageHandle Handle that identifies the loaded image.
+ @param SystemTable System Table for this image.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+LibRtcInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+
+/**
+ Fixup internal data so that EFI can be call in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+LibRtcVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+
+#endif
+
diff --git a/EmbeddedPkg/Include/Protocol/DebugSupportPeriodicCallback.h b/EmbeddedPkg/Include/Protocol/DebugSupportPeriodicCallback.h new file mode 100644 index 0000000000..d780cbd4cb --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/DebugSupportPeriodicCallback.h @@ -0,0 +1,42 @@ +/** @file
+ Protocol is used to help implement DebugSupport.RegisterPeriodicCallback() functionality.
+ This enables the DXE timer driver to support the periodic callback function so the
+ DebugSupport driver does not need to contain platform specific information about how a timer
+ works.
+
+ Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __DEBUG_SUPPORT_PERIODIC_CALLBACK_H__
+#define __DEBUG_SUPPORT_PERIODIC_CALLBACK_H__
+
+#include <Protocol/DebugSupport.h>
+
+typedef struct _EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL;
+
+
+// {9546E07C-2CBB-4c88-986C-CD341086F044}
+#define EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL_GUID \
+ { 0x9546e07c, 0x2cbb, 0x4c88, { 0x98, 0x6c, 0xcd, 0x34, 0x10, 0x86, 0xf0, 0x44 } }
+
+
+//
+// DebugSupport protocol definition
+//
+struct _EFI_DEBUG_SUPPORT_PERIODIC_CALLBACK_PROTOCOL {
+ EFI_PERIODIC_CALLBACK PeriodicCallback;
+};
+
+extern EFI_GUID gEfiDebugSupportPeriodicCallbackProtocolGuid;
+
+#endif
diff --git a/EmbeddedPkg/Include/Protocol/EblAddCommand.h b/EmbeddedPkg/Include/Protocol/EblAddCommand.h new file mode 100644 index 0000000000..2c11e7fe58 --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/EblAddCommand.h @@ -0,0 +1,156 @@ +/** @file
+
+ Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+/** @file
+ Abstraction for hardware based interrupt routine
+
+ Copyright (c) 2009 Apple Inc.
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __EBL_ADD_COMMAND_H__
+#define __EBL_ADD_COMMAND_H__
+
+
+
+//
+// Protocol GUID
+//
+// AEDA2428-9A22-4637-9B21-545E28FBB829
+
+#define EBL_ADD_COMMAND_PROTOCOL_GUID \
+ { 0xaeda2428, 0x9a22, 0x4637, { 0x9b, 0x21, 0x54, 0x5e, 0x28, 0xfb, 0xb8, 0x29 } }
+
+
+typedef struct _EBL_ADD_COMMAND_PROTOCOL EBL_ADD_COMMAND_PROTOCOL;
+
+typedef
+EFI_STATUS
+(EFIAPI *EBL_COMMMAND) (
+ IN UINTN Argc,
+ IN CHAR8 **Argv
+ );
+
+typedef struct {
+ CHAR8 *Name;
+ CHAR8 *HelpSummary;
+ CHAR8 *Help;
+ EBL_COMMMAND Command;
+} EBL_COMMAND_TABLE;
+
+
+/**
+ Add a single command table entry.
+
+ @param EntryArray Pointer EBL_COMMAND_TABLE of the command that is being added
+
+**/
+typedef
+VOID
+(EFIAPI *EBL_ADD_COMMAND) (
+ IN const EBL_COMMAND_TABLE *Entry
+ );
+
+
+/**
+ Add a multiple command table entry.
+
+ @param EntryArray Pointer EBL_COMMAND_TABLE of the commands that are being added
+
+ @param ArrayCount Nuber of commands in the EntryArray.
+
+**/
+typedef
+VOID
+(EFIAPI *EBL_ADD_COMMANDS) (
+ IN const EBL_COMMAND_TABLE *EntryArray,
+ IN UINTN ArrayCount
+ );
+
+
+typedef +VOID +(EFIAPI *EBL_GET_CHAR_CALL_BACK) ( + IN UINTN ElapsedTime + ); +
+/**
+ Return a keypress or optionally timeout if a timeout value was passed in.
+ An optional callback funciton is called evey second when waiting for a
+ timeout.
+
+ @param Key EFI Key information returned
+ @param TimeoutInSec Number of seconds to wait to timeout
+ @param CallBack Callback called every second during the timeout wait
+
+ @return EFI_SUCCESS Key was returned
+ @return EFI_TIMEOUT If the TimoutInSec expired
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EBL_GET_CHAR_KEY) (
+ IN OUT EFI_INPUT_KEY *Key,
+ IN UINTN TimeoutInSec,
+ IN EBL_GET_CHAR_CALL_BACK CallBack OPTIONAL
+ );
+
+
+/**
+ This routine is used prevent command output data from scrolling off the end
+ of the screen. The global gPageBreak is used to turn on or off this feature.
+ If the CurrentRow is near the end of the screen pause and print out a prompt
+ If the use hits Q to quit return TRUE else for any other key return FALSE.
+ PrefixNewline is used to figure out if a newline is needed before the prompt
+ string. This depends on the last print done before calling this function.
+ CurrentRow is updated by one on a call or set back to zero if a prompt is
+ needed.
+
+ @param CurrentRow Used to figure out if its the end of the page and updated
+ @param PrefixNewline Did previous print issue a newline
+
+ @return TRUE if Q was hit to quit, FALSE in all other cases.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EBL_ANY_KEY_CONTINUE_Q_QUIT) (
+ IN UINTN *CurrentRow,
+ IN BOOLEAN PrefixNewline
+ );
+
+
+
+struct _EBL_ADD_COMMAND_PROTOCOL {
+ EBL_ADD_COMMAND AddCommand;
+ EBL_ADD_COMMANDS AddCommands;
+
+ // Commands to reuse EBL infrastructure
+ EBL_GET_CHAR_KEY EblGetCharKey;
+ EBL_ANY_KEY_CONTINUE_Q_QUIT EblAnyKeyToContinueQtoQuit;
+};
+
+extern EFI_GUID gEfiEblAddCommandProtocolGuid;
+
+#endif
+
+
diff --git a/EmbeddedPkg/Include/Protocol/EmbeddedDevice.h b/EmbeddedPkg/Include/Protocol/EmbeddedDevice.h new file mode 100644 index 0000000000..4be6c11a28 --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/EmbeddedDevice.h @@ -0,0 +1,58 @@ +/** @file
+ Deal with devices that just exist in memory space.
+
+ To follow the EFI driver model you need a root handle to start with. An
+ EFI driver will have a driver binding protocol (Supported, Start, Stop)
+ that is used to layer on top of a handle via a gBS->ConnectController.
+ The first handle has to just be in the system to make that work. For
+ PCI it is a PCI Root Bridge IO protocol that provides the root.
+
+ On an embedded system with MMIO device we need a handle to just
+ show up. That handle will have this protocol and a device path
+ protocol on it.
+
+ For an ethernet device the device path must contain a MAC address device path
+ node.
+
+ Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EMBEDDED_DEVICE_PROTOCOL_H__
+#define __EMBEDDED_DEVICE_PROTOCOL_H__
+
+
+//
+// Protocol GUID
+//
+// BF4B9D10-13EC-43dd-8880-E90B718F27DE
+
+#define EMBEDDED_DEVICE_PROTOCOL_GUID \
+ { 0xbf4b9d10, 0x13ec, 0x43dd, { 0x88, 0x80, 0xe9, 0xb, 0x71, 0x8f, 0x27, 0xde } }
+
+
+
+typedef struct {
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT16 RevisionId;
+ UINT16 SubsystemId;
+ UINT16 SubsystemVendorId;
+ UINT8 ClassCode[3];
+ UINT8 HeaderSize;
+ UINTN BaseAddress;
+} EMBEDDED_DEVICE_PROTOCOL;
+
+extern EFI_GUID gEmbeddedDeviceGuid;
+
+#endif
+
+
diff --git a/EmbeddedPkg/Include/Protocol/EmbeddedExternalDevice.h b/EmbeddedPkg/Include/Protocol/EmbeddedExternalDevice.h new file mode 100644 index 0000000000..1131399a60 --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/EmbeddedExternalDevice.h @@ -0,0 +1,94 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EMBEDDED_EXTERNAL_DEVICE_H__ +#define __EMBEDDED_EXTERNAL_DEVICE_H__ + +// +// Protocol GUID +// +#define EMBEDDED_EXTERNAL_DEVICE_PROTOCOL_GUID { 0x735F8C64, 0xD696, 0x44D0, { 0xBD, 0xF2, 0x44, 0x7F, 0xD0, 0x5A, 0x54, 0x06 }} + +// +// Protocol interface structure +// +typedef struct _EMBEDDED_EXTERNAL_DEVICE EMBEDDED_EXTERNAL_DEVICE; + +// +// Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_EXTERNAL_DEVICE_READ) ( + IN EMBEDDED_EXTERNAL_DEVICE *This, + IN UINTN Register, + IN UINTN Length, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Read a set of contiguous external device registers. + +Arguments: + + This - pointer to protocol + Offset - starting register number + Length - number of bytes to read + Buffer - destination buffer + +Returns: + + EFI_SUCCESS - registers read successfully + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_EXTERNAL_DEVICE_WRITE) ( + IN EMBEDDED_EXTERNAL_DEVICE *This, + IN UINTN Register, + IN UINTN Length, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Write to a set of contiguous external device registers. + +Arguments: + + This - pointer to protocol + Offset - starting register number + Length - number of bytes to write + Buffer - source buffer + +Returns: + + EFI_SUCCESS - registers written successfully + +--*/ +; + +struct _EMBEDDED_EXTERNAL_DEVICE { + EMBEDDED_EXTERNAL_DEVICE_READ Read; + EMBEDDED_EXTERNAL_DEVICE_WRITE Write; +}; + +extern EFI_GUID gEmbeddedExternalDeviceProtocolGuid; + +#endif // __EMBEDDED_EXTERNAL_DEVICE_H__ diff --git a/EmbeddedPkg/Include/Protocol/EmbeddedGpio.h b/EmbeddedPkg/Include/Protocol/EmbeddedGpio.h new file mode 100644 index 0000000000..fd3d3bd9bc --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/EmbeddedGpio.h @@ -0,0 +1,167 @@ +/** @file + + Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR> + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EMBEDDED_GPIO_H__ +#define __EMBEDDED_GPIO_H__ + +// +// Protocol interface structure +// +typedef struct _EMBEDDED_GPIO EMBEDDED_GPIO; + +// +// Data Types +// +typedef UINTN EMBEDDED_GPIO_PIN; + +#define GPIO(Port, Pin) ((EMBEDDED_GPIO_PIN)(((Port) << (16)) | (Pin))) +#define GPIO_PIN(x) ((EMBEDDED_GPIO_PIN)(x) & (0xFFFF)) +#define GPIO_PORT(x) ((EMBEDDED_GPIO_PIN)(x) >> (16)) + +typedef enum { + GPIO_MODE_INPUT = 0x00, + GPIO_MODE_OUTPUT_0 = 0x0E, + GPIO_MODE_OUTPUT_1 = 0x0F, + GPIO_MODE_SPECIAL_FUNCTION_2 = 0x02, + GPIO_MODE_SPECIAL_FUNCTION_3 = 0x03, + GPIO_MODE_SPECIAL_FUNCTION_4 = 0x04, + GPIO_MODE_SPECIAL_FUNCTION_5 = 0x05, + GPIO_MODE_SPECIAL_FUNCTION_6 = 0x06, + GPIO_MODE_SPECIAL_FUNCTION_7 = 0x07 +} EMBEDDED_GPIO_MODE; + +typedef enum { + GPIO_PULL_NONE, + GPIO_PULL_UP, + GPIO_PULL_DOWN +} EMBEDDED_GPIO_PULL; + +// +// Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_GPIO_GET) ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT UINTN *Value + ); +/*++ + +Routine Description: + + Gets the state of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin to read + Value - state of the pin + +Returns: + + EFI_SUCCESS - GPIO state returned in Value + +--*/ + + +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_GPIO_SET) ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_MODE Mode + ); +/*++ + +Routine Description: + + Sets the state of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin to modify + Mode - mode to set + +Returns: + + EFI_SUCCESS - GPIO set as requested + +--*/ + + +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_GPIO_GET_MODE) ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + OUT EMBEDDED_GPIO_MODE *Mode + ); +/*++ + +Routine Description: + + Gets the mode (function) of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin + Mode - pointer to output mode value + +Returns: + + EFI_SUCCESS - mode value retrieved + +--*/ + + +typedef +EFI_STATUS +(EFIAPI *EMBEDDED_GPIO_SET_PULL) ( + IN EMBEDDED_GPIO *This, + IN EMBEDDED_GPIO_PIN Gpio, + IN EMBEDDED_GPIO_PULL Direction + ); +/*++ + +Routine Description: + + Sets the pull-up / pull-down resistor of a GPIO pin + +Arguments: + + This - pointer to protocol + Gpio - which pin + Direction - pull-up, pull-down, or none + +Returns: + + EFI_SUCCESS - pin was set + +--*/ + + + +struct _EMBEDDED_GPIO { + EMBEDDED_GPIO_GET Get; + EMBEDDED_GPIO_SET Set; + EMBEDDED_GPIO_GET_MODE GetMode; + EMBEDDED_GPIO_SET_PULL SetPull; +}; + +extern EFI_GUID gEmbeddedGpioProtocolGuid; + +#endif diff --git a/EmbeddedPkg/Include/Protocol/HardwareInterrupt.h b/EmbeddedPkg/Include/Protocol/HardwareInterrupt.h new file mode 100644 index 0000000000..a4825832c4 --- /dev/null +++ b/EmbeddedPkg/Include/Protocol/HardwareInterrupt.h @@ -0,0 +1,151 @@ +/** @file
+ Abstraction for hardware based interrupt routine
+
+ On non IA-32 systems it is common to have a single hardware interrupt vector
+ and a 2nd layer of software that routes the interrupt handlers based on the
+ interrupt source. This protocol enables this routing. The driver implementing
+ this protocol is responsible for clearing the pending interrupt in the
+ interrupt routing hardware. The HARDWARE_INTERRUPT_HANDLER is responsible
+ for clearing interrupt sources from individual devices.
+
+
+ Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __HARDWARE_INTERRUPT_H__
+#define __HARDWARE_INTERRUPT_H__
+
+#include <Protocol/DebugSupport.h>
+
+
+//
+// Protocol GUID
+//
+// EAB39028-3D05-4316-AD0C-D64808DA3FF1
+
+#define EFI_HARDWARE_INTERRUPT_PROTOCOL_GGUID \
+ { 0x2890B3EA, 0x053D, 0x1643, { 0xAD, 0x0C, 0xD6, 0x48, 0x08, 0xDA, 0x3F, 0xF1 } }
+
+
+typedef struct _EFI_HARDWARE_INTERRUPT_PROTOCOL EFI_HARDWARE_INTERRUPT_PROTOCOL;
+
+
+typedef UINTN HARDWARE_INTERRUPT_SOURCE;
+
+
+/**
+ C Interrupt Handler calledin the interrupt context when Source interrupt is active.
+
+ @param Source Source of the interrupt. Hardware routing off a specific platform defines
+ what source means.
+ @param SystemContext Pointer to system register context. Mostly used by debuggers and will
+ update the system context after the return from the interrupt if
+ modified. Don't change these values unless you know what you are doing
+
+**/
+typedef
+VOID
+(EFIAPI *HARDWARE_INTERRUPT_HANDLER) (
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+
+/**
+ Register Handler for the specified interrupt source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+ @param Handler Callback for interrupt. NULL to unregister
+
+ @retval EFI_SUCCESS Source was updated to support Handler.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *HARDWARE_INTERRUPT_REGISTER) (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN HARDWARE_INTERRUPT_HANDLER Handler
+ );
+
+
+/**
+ Enable interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt enabled.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *HARDWARE_INTERRUPT_ENABLE) (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ );
+
+
+
+/**
+ Disable interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+
+ @retval EFI_SUCCESS Source interrupt disabled.
+ @retval EFI_DEVICE_ERROR Hardware could not be programmed.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *HARDWARE_INTERRUPT_DISABLE) (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source
+ );
+
+
+/**
+ Return current state of interrupt source Source.
+
+ @param This Instance pointer for this protocol
+ @param Source Hardware source of the interrupt
+ @param InterruptState TRUE: source enabled, FALSE: source disabled.
+
+ @retval EFI_SUCCESS InterruptState is valid
+ @retval EFI_DEVICE_ERROR InterruptState is not valid
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *HARDWARE_INTERRUPT_INTERRUPT_STATE) (
+ IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
+ IN HARDWARE_INTERRUPT_SOURCE Source,
+ IN BOOLEAN *InterruptState
+ );
+
+
+struct _EFI_HARDWARE_INTERRUPT_PROTOCOL {
+ HARDWARE_INTERRUPT_REGISTER RegisterInterruptSource;
+ HARDWARE_INTERRUPT_ENABLE EnableInterruptSource;
+ HARDWARE_INTERRUPT_DISABLE DisableInterruptSource;
+ HARDWARE_INTERRUPT_INTERRUPT_STATE GetInterruptSourceState;
+};
+
+extern EFI_GUID gHardwareInterruptProtocolGuid;
+
+#endif
+
+
diff --git a/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.c b/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.c new file mode 100644 index 0000000000..fcb533c8b7 --- /dev/null +++ b/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.c @@ -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;
+}
+
diff --git a/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf b/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf new file mode 100644 index 0000000000..5b0af6e75a --- /dev/null +++ b/EmbeddedPkg/Library/EblAddExternalCommandLib/EblAddExternalCommandLib.inf @@ -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]
+
\ No newline at end of file diff --git a/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.c b/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.c new file mode 100644 index 0000000000..5cbdfdb15a --- /dev/null +++ b/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.c @@ -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;
+}
diff --git a/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf b/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf new file mode 100644 index 0000000000..b40935b838 --- /dev/null +++ b/EmbeddedPkg/Library/EblCmdLibNull/EblCmdLibNull.inf @@ -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]
+
\ No newline at end of file diff --git a/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.c b/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.c new file mode 100644 index 0000000000..13766c88b2 --- /dev/null +++ b/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.c @@ -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; +} + diff --git a/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf b/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf new file mode 100644 index 0000000000..f46242fc62 --- /dev/null +++ b/EmbeddedPkg/Library/EblNetworkLib/EblNetworkLib.inf @@ -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
\ No newline at end of file diff --git a/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c new file mode 100644 index 0000000000..e98651b14d --- /dev/null +++ b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c @@ -0,0 +1,1483 @@ +/** @file + File IO routines inspired by Streams with an EFI flavor + + 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. + + Basic support for opening files on different device types. The device string + is in the form of DevType:Path. Current DevType is required as there is no + current mounted device concept of current working directory concept implement + by this library. + + Device names are case insensative and only check the leading characters for + unique matches. Thus the following are all the same: + LoadFile0: + l0: + L0: + Lo0: + + Supported Device Names: + A0x1234:0x12 - A memory buffer starting at address 0x1234 for 0x12 bytes + l1: - EFI LoadFile device one. + B0: - EFI BlockIo zero. + fs3: - EFI Simple File System device 3 + Fv2: - EFI Firmware VOlume device 2 + 10.0.1.102: - TFTP service IP followed by the file name +**/ + +#include <PiDxe.h> +#include <Protocol/BlockIo.h> +#include <Protocol/DiskIo.h> +#include <Protocol/SimpleFileSystem.h> +#include <Protocol/FirmwareVolume2.h> +#include <Protocol/LoadFile.h> +#include <Protocol/FirmwareVolumeBlock.h> +#include <Guid/FileInfo.h> +#include <Library/BaseLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DevicePathLib.h> +#include <Library/PrintLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/DebugLib.h> +#include <Library/EfiFileLib.h> +#include <Library/PcdLib.h> +#include <Library/EblNetworkLib.h> + + +#define EFI_OPEN_FILE_GUARD_HEADER 0x4B4D4641 +#define EFI_OPEN_FILE_GUARD_FOOTER 0x444D5A56 + +// Need to defend against this overflowing +#define MAX_CMD_LINE 0x200 + +typedef struct { + UINT32 Header; + EFI_OPEN_FILE File; + UINT32 Footer; +} EFI_OPEN_FILE_GUARD; + + +// globals to store current open device info +EFI_HANDLE *mBlkIo = NULL; +UINTN mBlkIoCount = 0; + +EFI_HANDLE *mFs = NULL; +UINTN mFsCount = 0; +// mFsInfo[] array entries must match mFs[] handles +EFI_FILE_SYSTEM_INFO **mFsInfo = NULL; + +EFI_HANDLE *mFv = NULL; +UINTN mFvCount = 0; +EFI_HANDLE *mLoadFile = NULL; +UINTN mLoadFileCount = 0; + + + +/** + Internal worker function to validate a File handle. + + @param File Open File Handle + + @return TRUE File is valid + @return FALSE File is not valid + + +**/ +BOOLEAN +FileHandleValid ( + IN EFI_OPEN_FILE *File + ) +{ + EFI_OPEN_FILE_GUARD *GuardFile; + + // Look right before and after file structure for the correct signatures + GuardFile = BASE_CR (File, EFI_OPEN_FILE_GUARD, File); + if ((GuardFile->Header != EFI_OPEN_FILE_GUARD_HEADER) || + (GuardFile->Footer != EFI_OPEN_FILE_GUARD_FOOTER) ) { + return FALSE; + } + + return TRUE; +} + +/** + Internal worker function. If Buffer is not NULL free it. + + @param Buffer Buffer to FreePool() + +**/ +VOID +EblFreePool ( + IN VOID *Buffer + ) +{ + if (Buffer != NULL) { + FreePool (Buffer); + } +} + +/** + Update Device List Global Variables + +**/ +VOID +EblUpdateDeviceLists ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Size; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + EFI_FILE_HANDLE Root; + UINTN Index; + + if (mBlkIo != NULL) { + FreePool (mBlkIo); + } + gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &mBlkIoCount, &mBlkIo); + + if (mFv != NULL) { + FreePool (mFv); + } + gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &mFvCount, &mFv); + + if (mLoadFile != NULL) { + FreePool (mLoadFile); + } + gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &mLoadFileCount, &mLoadFile); + + if (mFs != NULL) { + FreePool (mFs); + } + + if (&mFsInfo[0] != NULL) { + // Need to Free the mFsInfo prior to reclaculating mFsCount so don't move this code + for (Index = 0; Index < mFsCount; Index++) { + if (mFsInfo[Index] != NULL) { + FreePool (mFsInfo[Index]); + } + } + FreePool (mFsInfo); + } + + gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &mFsCount, &mFs); + + + mFsInfo = AllocateZeroPool (mFsCount * sizeof (EFI_FILE_SYSTEM_INFO *)); + if (mFsInfo == NULL) { + // If we can't do this then we can't support file system entries + mFsCount = 0; + } else { + // Loop through all the file system structures and cache the file system info data + for (Index =0; Index < mFsCount; Index++) { + Status = gBS->HandleProtocol (mFs[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs); + if (!EFI_ERROR (Status)) { + Status = Fs->OpenVolume (Fs, &Root); + if (!EFI_ERROR (Status)) { + // Get information about the volume + Size = 0; + Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]); + if (Status == EFI_BUFFER_TOO_SMALL) { + mFsInfo[Index] = AllocatePool (Size); + Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]); + } + + Root->Close (Root); + } + } + } + } +} + + +/** + PathName is in the form <device name>:<path> for example fs1:\ or ROOT:\. + Return TRUE if the <devce name> prefix of PathName matches a file system + Volume Name. MatchIndex is the array index in mFsInfo[] of the match, + and it can be used with mFs[] to find the handle that needs to be opened + + @param PathName PathName to check + @param FileStart Index of the first character of the <path> + @param MatchIndex Index in mFsInfo[] that matches + + @return TRUE PathName matches a Volume Label and MatchIndex is valid + @return FALSE PathName does not match a Volume Label MatchIndex undefined + +**/ +BOOLEAN +EblMatchVolumeName ( + IN CHAR8 *PathName, + IN UINTN FileStart, + OUT UINTN *MatchIndex + ) +{ + UINTN Index; + UINTN Compare; + UINTN VolStrLen; + BOOLEAN Match; + + for (Index =0; Index < mFsCount; Index++) { + if (mFsInfo[Index] == NULL) { + // FsInfo is not valid so skip it + continue; + } + VolStrLen = StrLen (mFsInfo[Index]->VolumeLabel); + for (Compare = 0, Match = TRUE; Compare < (FileStart - 1); Compare++) { + if (Compare > VolStrLen) { + Match = FALSE; + break; + } + if (PathName[Compare] != (CHAR8)mFsInfo[Index]->VolumeLabel[Compare]) { + // If the VolumeLabel has a space allow a _ to match with it in addition to ' ' + if (!((PathName[Compare] == '_') && (mFsInfo[Index]->VolumeLabel[Compare] == L' '))) { + Match = FALSE; + break; + } + } + } + if (Match) { + *MatchIndex = Index; + return TRUE; + } + } + + return FALSE; +} + + +/** + Return the number of devices of the current type active in the system + + @param Type Device type to check + + @return 0 Invalid type + +**/ +UINTN +EfiGetDeviceCounts ( + IN EFI_OPEN_FILE_TYPE DeviceType + ) +{ + switch (DeviceType) { + case EfiOpenLoadFile: + return mLoadFileCount; + case EfiOpenFirmwareVolume: + return mFvCount; + case EfiOpenFileSystem: + return mFsCount; + case EfiOpenBlockIo: + return mBlkIoCount; + default: + return 0; + } +} + +EFI_STATUS +ConvertIpStringToEfiIp ( + IN CHAR8 *PathName, + OUT EFI_IP_ADDRESS *ServerIp + ) +{ + CHAR8 *Str; + + Str = PathName; + ServerIp->v4.Addr[0] = (UINT8)AsciiStrDecimalToUintn (Str); + + Str = AsciiStrStr (Str, "."); + if (Str == NULL) { + return EFI_DEVICE_ERROR; + } + + ServerIp->v4.Addr[1] = (UINT8)AsciiStrDecimalToUintn (++Str); + + Str = AsciiStrStr (Str, "."); + if (Str == NULL) { + return EFI_DEVICE_ERROR; + } + + ServerIp->v4.Addr[2] = (UINT8)AsciiStrDecimalToUintn (++Str); + + Str = AsciiStrStr (Str, "."); + if (Str == NULL) { + return EFI_DEVICE_ERROR; + } + + ServerIp->v4.Addr[3] = (UINT8)AsciiStrDecimalToUintn (++Str); + + return EFI_SUCCESS; +} + + +/** + Internal work function to extract a device number from a string skipping + text. Easy way to extract numbers from strings like blk7:. + + @param Str String to extract device number form + + @return -1 Device string is not valid + @return Device # + +**/ +UINTN +EblConvertDevStringToNumber ( + IN CHAR8 *Str + ) +{ + UINTN Max; + UINTN Index; + + + // Find the first digit + Max = AsciiStrLen (Str); + for (Index = 0; !((*Str >= '0') && (*Str <= '9')) && (Index < Max); Index++) { + Str++; + } + if (Index == Max) { + return (UINTN)-1; + } + + return AsciiStrDecimalToUintn (Str); +} + + +/** + Internal work function to fill in EFI_OPEN_FILE information for the Fs and BlkIo + + @param File Open file handle + @param FileName Name of file after device stripped off + + +**/ +EFI_STATUS +EblFileDevicePath ( + IN OUT EFI_OPEN_FILE *File, + IN CHAR8 *FileName, + IN CONST UINT64 OpenMode + ) +{ + EFI_STATUS Status; + UINTN Size; + FILEPATH_DEVICE_PATH *FilePath; + EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; + CHAR16 UnicodeFileName[MAX_PATHNAME]; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; + EFI_FILE_HANDLE Root; + + + if ( *FileName != 0 ) { + AsciiStrToUnicodeStr (FileName, UnicodeFileName); + } else { + AsciiStrToUnicodeStr ("\\", UnicodeFileName); + } + + Size = StrSize (UnicodeFileName); + FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL)); + if (FileDevicePath != NULL) { + FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; + FilePath->Header.Type = MEDIA_DEVICE_PATH; + FilePath->Header.SubType = MEDIA_FILEPATH_DP; + CopyMem (&FilePath->PathName, UnicodeFileName, Size); + SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); + SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); + + if (File->EfiHandle != NULL) { + File->DevicePath = DevicePathFromHandle (File->EfiHandle); + } + + File->DevicePath = AppendDevicePath (File->DevicePath, FileDevicePath); + FreePool (FileDevicePath); + } + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlkIo); + if (!EFI_ERROR (Status)) { + CopyMem (&File->FsBlockIoMedia, BlkIo->Media, sizeof (EFI_BLOCK_IO_MEDIA)); + + // If we are not opening the device this will get over written with file info + File->MaxPosition = MultU64x32 (BlkIo->Media->LastBlock + 1, BlkIo->Media->BlockSize); + } + + if (File->Type == EfiOpenFileSystem) { + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs); + if (!EFI_ERROR (Status)) { + Status = Fs->OpenVolume (Fs, &Root); + if (!EFI_ERROR (Status)) { + // Get information about the volume + Size = 0; + Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo); + if (Status == EFI_BUFFER_TOO_SMALL) { + File->FsInfo = AllocatePool (Size); + Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo); + } + + // Get information about the file + Status = Root->Open (Root, &File->FsFileHandle, UnicodeFileName, OpenMode, 0); + if (!EFI_ERROR (Status)) { + Size = 0; + Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, NULL); + if (Status == EFI_BUFFER_TOO_SMALL) { + File->FsFileInfo = AllocatePool (Size); + Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, File->FsFileInfo); + if (!EFI_ERROR (Status)) { + File->Size = (UINTN)File->FsFileInfo->FileSize; + File->MaxPosition = (UINT64)File->Size; + } + } + } + + Root->Close (Root); + } + } + } else if (File->Type == EfiOpenBlockIo) { + File->Size = (UINTN)File->MaxPosition; + } + + return Status; +} + +#define ToUpper(a) ((((a) >= 'a') && ((a) <= 'z')) ? ((a) - 'a' + 'A') : (a)) + +EFI_STATUS +CompareGuidToString ( + IN EFI_GUID *Guid, + IN CHAR8 *String + ) +{ + CHAR8 AsciiGuid[64]; + CHAR8 *StringPtr; + CHAR8 *GuidPtr; + + AsciiSPrint (AsciiGuid, sizeof(AsciiGuid), "%g", Guid); + + StringPtr = String; + GuidPtr = AsciiGuid; + + while ((*StringPtr != '\0') && (*GuidPtr != '\0')) { + // Skip dashes + if (*StringPtr == '-') { + StringPtr++; + continue; + } + + if (*GuidPtr == '-') { + GuidPtr++; + continue; + } + + if (ToUpper(*StringPtr) != ToUpper(*GuidPtr)) { + return EFI_NOT_FOUND; + } + + StringPtr++; + GuidPtr++; + } + + return EFI_SUCCESS; +} + + +/** + Internal work function to fill in EFI_OPEN_FILE information for the FV + + @param File Open file handle + @param FileName Name of file after device stripped off + + +**/ +EFI_STATUS +EblFvFileDevicePath ( + IN OUT EFI_OPEN_FILE *File, + IN CHAR8 *FileName, + IN CONST UINT64 OpenMode + ) +{ + EFI_STATUS Status; + EFI_STATUS GetNextFileStatus; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH DevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN Key; + UINT32 AuthenticationStatus; + CHAR8 AsciiSection[MAX_PATHNAME]; + VOID *Section; + UINTN SectionSize; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_LBA Lba; + UINTN BlockSize; + UINTN NumberOfBlocks; + + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&File->Fv); + if (EFI_ERROR (Status)) { + return Status; + } + + DevicePath = DevicePathFromHandle (File->EfiHandle); + + if (*FileName == '\0') { + File->DevicePath = DuplicateDevicePath (DevicePath); + } else { + Key = 0; + do { + File->FvType = EFI_FV_FILETYPE_ALL; + GetNextFileStatus = File->Fv->GetNextFile ( + File->Fv, + &Key, + &File->FvType, + &File->FvNameGuid, + &File->FvAttributes, + &File->Size + ); + if (!EFI_ERROR (GetNextFileStatus)) { + Section = NULL; + + // Compare GUID first + Status = CompareGuidToString (&File->FvNameGuid, FileName); + if (!EFI_ERROR(Status)) { + break; + } + + Status = File->Fv->ReadSection ( + File->Fv, + &File->FvNameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + &Section, + &SectionSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + UnicodeStrToAsciiStr (Section, AsciiSection); + if (AsciiStriCmp (FileName, AsciiSection) == 0) { + FreePool (Section); + break; + } + FreePool (Section); + } + } + } while (!EFI_ERROR (GetNextFileStatus)); + + if (EFI_ERROR (GetNextFileStatus)) { + return GetNextFileStatus; + } + + File->MaxPosition = File->Size; + EfiInitializeFwVolDevicepathNode (&DevicePathNode, &File->FvNameGuid); + File->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&DevicePathNode); + } + + + // Get FVB Info about the handle + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb); + if (!EFI_ERROR (Status)) { + Status = Fvb->GetPhysicalAddress (Fvb, &File->FvStart); + if (!EFI_ERROR (Status)) { + for (Lba = 0, File->FvSize = 0; ; File->FvSize += (BlockSize * NumberOfBlocks), Lba += NumberOfBlocks) { + Status = Fvb->GetBlockSize (Fvb, Lba, &BlockSize, &NumberOfBlocks); + if (EFI_ERROR (Status)) { + break; + } + } + } + } + + // FVB not required if FV was soft loaded... + return EFI_SUCCESS; +} + + + + +/** + Open a device named by PathName. The PathName includes a device name and + path seperated by a :. See file header for more details on the PathName + syntax. There is no checking to prevent a file from being opened more than + one type. + + SectionType is only used to open an FV. Each file in an FV contains multiple + secitons and only the SectionType section is opened. + + For any file that is opened with EfiOpen() must be closed with EfiClose(). + + @param PathName Path to parse to open + @param OpenMode Same as EFI_FILE.Open() + @param SectionType Section in FV to open. + + @return NULL Open failed + @return Valid EFI_OPEN_FILE handle + +**/ +EFI_OPEN_FILE * +EfiOpen ( + IN CHAR8 *PathName, + IN CONST UINT64 OpenMode, + IN CONST EFI_SECTION_TYPE SectionType + ) +{ + EFI_STATUS Status; + EFI_OPEN_FILE *File; + EFI_OPEN_FILE FileData; + UINTN StrLen; + UINTN FileStart; + UINTN DevNumber = 0; + EFI_OPEN_FILE_GUARD *GuardFile; + BOOLEAN VolumeNameMatch; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN Size; + EFI_IP_ADDRESS Ip; + + EblUpdateDeviceLists (); + + File = &FileData; + ZeroMem (File, sizeof (EFI_OPEN_FILE)); + File->FvSectionType = SectionType; + + StrLen = AsciiStrSize (PathName); + if (StrLen <= 2) { + // Smallest valid path is 1 char and a null + return NULL; + } + + for (FileStart = 0; FileStart < StrLen; FileStart++) { + if (PathName[FileStart] == ':') { + FileStart++; + break; + } + } + + if (FileStart == 0) { + // We could add a current working diretory concept + return NULL; + } + + // + // Matching volume name has precedence over handle based names + // + VolumeNameMatch = EblMatchVolumeName (PathName, FileStart, &DevNumber); + if (!VolumeNameMatch) { + DevNumber = EblConvertDevStringToNumber ((CHAR8 *)PathName); + } + + File->DeviceName = AllocatePool (StrLen); + AsciiStrCpy (File->DeviceName, PathName); + File->DeviceName[FileStart - 1] = '\0'; + File->FileName = &File->DeviceName[FileStart]; + + // + // Use best match algorithm on the dev names so we only need to look at the + // first few charters to match the full device name. Short name forms are + // legal from the caller. + // + Status = EFI_SUCCESS; + if (*PathName == 'f' || *PathName == 'F' || VolumeNameMatch) { + if (PathName[1] == 's' || PathName[1] == 'S' || VolumeNameMatch) { + if (DevNumber >= mFsCount) { + goto ErrorExit; + } + File->Type = EfiOpenFileSystem; + File->EfiHandle = mFs[DevNumber]; + Status = EblFileDevicePath (File, &PathName[FileStart], OpenMode); + + } else if (PathName[1] == 'v' || PathName[1] == 'V') { + if (DevNumber >= mFvCount) { + goto ErrorExit; + } + File->Type = EfiOpenFirmwareVolume; + File->EfiHandle = mFv[DevNumber]; + + if ((PathName[FileStart] == '/') || (PathName[FileStart] == '\\')) { + // Skip leading / as its not really needed for the FV since no directories are supported + FileStart++; + } + Status = EblFvFileDevicePath (File, &PathName[FileStart], OpenMode); + } + } else if ((*PathName == 'A') || (*PathName == 'a')) { + // Handle a:0x10000000:0x1234 address form a:ADDRESS:SIZE + File->Type = EfiOpenMemoryBuffer; + // 1st colon is at PathName[FileStart - 1] + File->Buffer = (VOID *)AsciiStrHexToUintn (&PathName[FileStart]); + + // Find 2nd colon + while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) { + FileStart++; + } + + // If we ran out of string, there's no extra data + if (PathName[FileStart] == '\0') { + File->Size = 0; + } else { + File->Size = AsciiStrHexToUintn (&PathName[FileStart + 1]); + } + + // if there's no number after the second colon, default + // the end of memory + if (File->Size == 0) { + File->Size = (UINTN)(0 - (UINTN)File->Buffer); + } + + File->MaxPosition = File->Size; + File->BaseOffset = (UINTN)File->Buffer; + + } else if (*PathName== 'l' || *PathName == 'L') { + if (DevNumber >= mLoadFileCount) { + goto ErrorExit; + } + File->Type = EfiOpenLoadFile; + File->EfiHandle = mLoadFile[DevNumber]; + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiLoadFileProtocolGuid, (VOID **)&File->LoadFile); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + File->DevicePath = DuplicateDevicePath (DevicePath); + + } else if (*PathName == 'b' || *PathName == 'B') { + // Handle b#:0x10000000:0x1234 address form b#:ADDRESS:SIZE + if (DevNumber >= mBlkIoCount) { + goto ErrorExit; + } + File->Type = EfiOpenBlockIo; + File->EfiHandle = mBlkIo[DevNumber]; + EblFileDevicePath (File, "", OpenMode); + + // 1st colon is at PathName[FileStart - 1] + File->DiskOffset = AsciiStrHexToUintn (&PathName[FileStart]); + + // Find 2nd colon + while ((PathName[FileStart] != ':') && (PathName[FileStart] != '\0')) { + FileStart++; + } + + // If we ran out of string, there's no extra data + if (PathName[FileStart] == '\0') { + Size = 0; + } else { + Size = AsciiStrHexToUintn (&PathName[FileStart + 1]); + } + + // if a zero size is passed in (or the size is left out entirely), + // go to the end of the device. + if (Size == 0) { + File->Size = File->Size - File->DiskOffset; + } else { + File->Size = Size; + } + + File->MaxPosition = File->Size; + File->BaseOffset = File->DiskOffset; + } else if ((*PathName) >= '0' && (*PathName <= '9')) { + + // Get current IP address + Status = EblGetCurrentIpAddress (&Ip); + if (EFI_ERROR(Status)) { + AsciiPrint("Device IP Address is not configured.\n"); + goto ErrorExit; + } + + + // Parse X.X.X.X:Filename, only support IPv4 TFTP for now... + File->Type = EfiOpenTftp; + File->IsDirty = FALSE; + File->IsBufferValid = FALSE; + + Status = ConvertIpStringToEfiIp (PathName, &File->ServerIp); + } + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + GuardFile = (EFI_OPEN_FILE_GUARD *)AllocateZeroPool (sizeof (EFI_OPEN_FILE_GUARD)); + if (GuardFile == NULL) { + goto ErrorExit; + } + + GuardFile->Header = EFI_OPEN_FILE_GUARD_HEADER; + CopyMem (&(GuardFile->File), &FileData, sizeof (EFI_OPEN_FILE)); + GuardFile->Footer = EFI_OPEN_FILE_GUARD_FOOTER; + + return &(GuardFile->File); + +ErrorExit: + FreePool (File->DeviceName); + return NULL; +} + +#define FILE_COPY_CHUNK 0x01000000 + +EFI_STATUS +EfiCopyFile ( + IN CHAR8 *DestinationFile, + IN CHAR8 *SourceFile + ) +{ + EFI_OPEN_FILE *Source = NULL; + EFI_OPEN_FILE *Destination = NULL; + EFI_STATUS Status = EFI_SUCCESS; + VOID *Buffer = NULL; + UINTN Size; + UINTN Offset; + UINTN Chunk = FILE_COPY_CHUNK; + + Source = EfiOpen(SourceFile, EFI_FILE_MODE_READ, 0); + if (Source == NULL) { + AsciiPrint("Source file open error.\n"); + Status = EFI_NOT_FOUND; + goto Exit; + } + + Destination = EfiOpen(DestinationFile, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0); + if (Destination == NULL) { + AsciiPrint("Destination file open error.\n"); + Status = EFI_NOT_FOUND; + goto Exit; + } + + Buffer = AllocatePool(FILE_COPY_CHUNK); + if (Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + Size = EfiTell(Source, NULL); + + for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size; Offset += Chunk) { + Chunk = FILE_COPY_CHUNK; + + Status = EfiRead(Source, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Read file error\n"); + goto Exit; + } + + Status = EfiWrite(Destination, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Write file error\n"); + goto Exit; + } + } + + // Any left over? + if (Offset < Size) { + Chunk = Size - Offset; + + Status = EfiRead(Source, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Read file error\n"); + goto Exit; + } + + Status = EfiWrite(Destination, Buffer, &Chunk); + if (EFI_ERROR(Status)) { + AsciiPrint("Write file error\n"); + goto Exit; + } + } + +Exit: + if (Source != NULL) { + Status = EfiClose(Source); + if (EFI_ERROR(Status)) { + AsciiPrint("Source close error"); + } + } + + if (Destination != NULL) { + Status = EfiClose(Destination); + if (EFI_ERROR(Status)) { + AsciiPrint("Destination close error"); + } + } + + if (Buffer != NULL) { + FreePool(Buffer); + } + + return Status; +} + +/** + Use DeviceType and Index to form a valid PathName and try and open it. + + @param DeviceType Device type to open + @param Index Device Index to use. Zero relative. + + @return NULL Open failed + @return Valid EFI_OPEN_FILE handle + +**/ +EFI_OPEN_FILE * +EfiDeviceOpenByType ( + IN EFI_OPEN_FILE_TYPE DeviceType, + IN UINTN Index + ) +{ + CHAR8 *DevStr; + CHAR8 Path[MAX_CMD_LINE]; + + switch (DeviceType) { + case EfiOpenLoadFile: + DevStr = "loadfile%d:"; + break; + case EfiOpenFirmwareVolume: + DevStr = "fv%d:"; + break; + case EfiOpenFileSystem: + DevStr = "fs%d:"; + break; + case EfiOpenBlockIo: + DevStr = "blk%d:"; + break; + case EfiOpenMemoryBuffer: + DevStr = "a%d:"; + break; + default: + return NULL; + } + + AsciiSPrint (Path, MAX_PATHNAME, DevStr, Index); + + return EfiOpen (Path, EFI_FILE_MODE_READ, 0); +} + + +/** + Close a file handle opened by EfiOpen() and free all resources allocated by + EfiOpen(). + + @param Stream Open File Handle + + @return EFI_INVALID_PARAMETER Stream is not an Open File + @return EFI_SUCCESS Steam closed + +**/ +EFI_STATUS +EfiClose ( + IN EFI_OPEN_FILE *File + ) +{ + EFI_STATUS Status; + UINT64 TftpBufferSize; + + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + //Write the buffer contents to TFTP file. + if ((File->Type == EfiOpenTftp) && (File->IsDirty)) { + + TftpBufferSize = File->Size; + Status = EblMtftp ( + EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, + File->Buffer, + TRUE, + &TftpBufferSize, + NULL, + &File->ServerIp, + (UINT8 *)File->FileName, + NULL, + FALSE + ); + if (EFI_ERROR(Status)) { + AsciiPrint("TFTP error during APPLE_NSP_TFTP_WRITE_FILE: %r\n", Status); + return Status; + } + } + + if ((File->Type == EfiOpenLoadFile) || + ((File->Type == EfiOpenTftp) && (File->IsBufferValid == TRUE))) { + EblFreePool(File->Buffer); + } + + EblFreePool (File->DevicePath); + EblFreePool (File->DeviceName); + EblFreePool (File->FsFileInfo); + EblFreePool (File->FsInfo); + + if (File->FsFileHandle != NULL) { + File->FsFileHandle->Close (File->FsFileHandle); + } + + // Need to free File and it's Guard structures + EblFreePool (BASE_CR (File, EFI_OPEN_FILE_GUARD, File)); + return EFI_SUCCESS; +} + + +/** + Return the size of the file represented by Stream. Also return the current + Seek position. Opening a file will enable a valid file size to be returned. + LoadFile is an exception as a load file size is set to zero. + + @param Stream Open File Handle + + @return 0 Stream is not an Open File or a valid LoadFile handle + +**/ +UINTN +EfiTell ( + IN EFI_OPEN_FILE *File, + OUT EFI_LBA *CurrentPosition OPTIONAL + ) +{ + EFI_STATUS Status; + UINT64 BufferSize = 0; + + if (!FileHandleValid (File)) { + return 0; + } + + if (CurrentPosition != NULL) { + *CurrentPosition = File->CurrentPosition; + } + + if (File->Type == EfiOpenLoadFile) { + // Figure out the File->Size + File->Buffer = NULL; + File->Size = 0; + Status = File->LoadFile->LoadFile (File->LoadFile, File->DevicePath, FALSE, &File->Size, File->Buffer); + if (Status != EFI_BUFFER_TOO_SMALL) { + return 0; + } + + File->MaxPosition = (UINT64)File->Size; + } else if (File->Type == EfiOpenTftp) { + + Status = EblMtftp ( + EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, + NULL, + FALSE, + &BufferSize, + NULL, + &File->ServerIp, + (UINT8 *)File->FileName, + NULL, + TRUE + ); + if (EFI_ERROR(Status)) { + AsciiPrint("TFTP error during APPLE_NSP_TFTP_GET_FILE_SIZE: %r\n", Status); + return 0; + } + + File->Size = BufferSize; + File->MaxPosition = File->Size; + } + + return File->Size; +} + + +/** + Seek to the Offset locaiton in the file. LoadFile and FV device types do + not support EfiSeek(). It is not possible to grow the file size using + EfiSeek(). + + SeekType defines how use Offset to calculate the new file position: + EfiSeekStart : Position = Offset + EfiSeekCurrent: Position is Offset bytes from the current position + EfiSeekEnd : Only supported if Offset is zero to seek to end of file. + + @param Stream Open File Handle + @param Offset Offset to seek too. + @param SeekType Type of seek to perform + + + @return EFI_INVALID_PARAMETER Stream is not an Open File + @return EFI_UNSUPPORTED LoadFile and FV doe not support Seek + @return EFI_NOT_FOUND Seek past the end of the file. + @return EFI_SUCCESS Steam closed + +**/ +EFI_STATUS +EfiSeek ( + IN EFI_OPEN_FILE *File, + IN EFI_LBA Offset, + IN EFI_SEEK_TYPE SeekType + ) +{ + EFI_STATUS Status; + UINT64 CurrentPosition; + + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + if (File->Type == EfiOpenLoadFile || File->Type == EfiOpenFirmwareVolume) { + // LoadFile and FV do not support Seek + return EFI_UNSUPPORTED; + } + + CurrentPosition = File->CurrentPosition; + switch (SeekType) { + case EfiSeekStart: + if (Offset > File->MaxPosition) { + return EFI_NOT_FOUND; + } + CurrentPosition = Offset; + break; + + case EfiSeekCurrent: + if ((File->CurrentPosition + Offset) > File->MaxPosition) { + return EFI_NOT_FOUND; + } + CurrentPosition += Offset; + break; + + case EfiSeekEnd: + if (Offset != 0) { + // We don't support growing file size via seeking past end of file + return EFI_UNSUPPORTED; + } + CurrentPosition = File->MaxPosition; + break; + + default: + return EFI_NOT_FOUND; + } + + Status = EFI_SUCCESS; + if (File->FsFileHandle != NULL) { + Status = File->FsFileHandle->SetPosition (File->FsFileHandle, CurrentPosition); + } + + if (!EFI_ERROR (Status)) { + File->CurrentPosition = CurrentPosition; + } + + return Status; +} + +EFI_STATUS +CacheTftpFile ( + IN OUT EFI_OPEN_FILE *File + ) +{ + EFI_STATUS Status; + UINT64 TftpBufferSize; + + if (File->IsBufferValid) { + return EFI_SUCCESS; + } + + // Make sure the file size is set. + EfiTell (File, NULL); + + //Allocate a buffer to hold the whole file. + File->Buffer = AllocatePool(File->Size); + if (File->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TftpBufferSize = File->Size; + + Status = EblMtftp ( + EFI_PXE_BASE_CODE_TFTP_READ_FILE, + File->Buffer, + FALSE, + &TftpBufferSize, + NULL, + &File->ServerIp, + (UINT8 *)File->FileName, + NULL, + FALSE); + if (EFI_ERROR(Status)) { + AsciiPrint("TFTP error during APPLE_NSP_TFTP_READ_FILE: %r\n", Status); + FreePool(File->Buffer); + return Status; + } + + // Set the buffer valid flag. + File->IsBufferValid = TRUE; + + return Status; +} + +/** + Read BufferSize bytes from the current locaiton in the file. For load file, + FV, and TFTP case you must read the entire file. + + @param Stream Open File Handle + @param Buffer Caller allocated buffer. + @param BufferSize Size of buffer in bytes. + + + @return EFI_SUCCESS Stream is not an Open File + @return EFI_END_OF_FILE Tried to read past the end of the file + @return EFI_INVALID_PARAMETER Stream is not an open file handle + @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read + @return "other" Error returned from device read + +**/ +EFI_STATUS +EfiRead ( + IN EFI_OPEN_FILE *File, + OUT VOID *Buffer, + OUT UINTN *BufferSize + ) +{ + EFI_STATUS Status; + UINT32 AuthenticationStatus; + EFI_DISK_IO_PROTOCOL *DiskIo; + + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + // Don't read past the end of the file. + if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) { + return EFI_END_OF_FILE; + } + + switch (File->Type) { + case EfiOpenMemoryBuffer: + CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize); + File->CurrentPosition += *BufferSize; + Status = EFI_SUCCESS; + break; + + case EfiOpenLoadFile: + // Figure out the File->Size + EfiTell (File, NULL); + + Status = File->LoadFile->LoadFile (File->LoadFile, File->DevicePath, FALSE, BufferSize, Buffer); + break; + + case EfiOpenFirmwareVolume: + if (File->FvSectionType == EFI_SECTION_ALL) { + Status = File->Fv->ReadFile ( + File->Fv, + &File->FvNameGuid, + &Buffer, + BufferSize, + &File->FvType, + &File->FvAttributes, + &AuthenticationStatus + ); + } else { + Status = File->Fv->ReadSection ( + File->Fv, + &File->FvNameGuid, + File->FvSectionType, + 0, + &Buffer, + BufferSize, + &AuthenticationStatus + ); + } + break; + + case EfiOpenFileSystem: + Status = File->FsFileHandle->Read (File->FsFileHandle, BufferSize, Buffer); + File->CurrentPosition += *BufferSize; + break; + + case EfiOpenBlockIo: + Status = gBS->HandleProtocol(File->EfiHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo); + if (!EFI_ERROR(Status)) { + Status = DiskIo->ReadDisk(DiskIo, File->FsBlockIoMedia.MediaId, File->DiskOffset + File->CurrentPosition, *BufferSize, Buffer); + } + File->CurrentPosition += *BufferSize; + break; + + case EfiOpenTftp: + // Cache the file if it hasn't been cached yet. + if (File->IsBufferValid == FALSE) { + Status = CacheTftpFile (File); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // Copy out the requested data + CopyMem (Buffer, File->Buffer + File->CurrentPosition, *BufferSize); + File->CurrentPosition += *BufferSize; + + Status = EFI_SUCCESS; + break; + + default: + return EFI_INVALID_PARAMETER; + }; + + return Status; +} + + +/** + Read the entire file into a buffer. This routine allocates the buffer and + returns it to the user full of the read data. + + This is very useful for load flie where it's hard to know how big the buffer + must be. + + @param Stream Open File Handle + @param Buffer Pointer to buffer to return. + @param BufferSize Pointer to Size of buffer return.. + + + @return EFI_SUCCESS Stream is not an Open File + @return EFI_END_OF_FILE Tried to read past the end of the file + @return EFI_INVALID_PARAMETER Stream is not an open file handle + @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read + @return "other" Error returned from device read + +**/ +EFI_STATUS +EfiReadAllocatePool ( + IN EFI_OPEN_FILE *File, + OUT VOID **Buffer, + OUT UINTN *BufferSize + ) +{ + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + // Loadfile defers file size determination on Open so use tell to find it + EfiTell (File, NULL); + + *BufferSize = File->Size; + *Buffer = AllocatePool (*BufferSize); + if (*Buffer == NULL) { + return EFI_NOT_FOUND; + } + + return EfiRead (File, *Buffer, BufferSize); +} + + +/** + Write data back to the file. For TFTP case you must write the entire file. + + @param Stream Open File Handle + @param Buffer Pointer to buffer to return. + @param BufferSize Pointer to Size of buffer return.. + + + @return EFI_SUCCESS Stream is not an Open File + @return EFI_END_OF_FILE Tried to read past the end of the file + @return EFI_INVALID_PARAMETER Stream is not an open file handle + @return EFI_BUFFER_TOO_SMALL Buffer is not big enough to do the read + @return "other" Error returned from device write + +**/ +EFI_STATUS +EfiWrite ( + IN EFI_OPEN_FILE *File, + OUT VOID *Buffer, + OUT UINTN *BufferSize + ) +{ + EFI_STATUS Status; + EFI_FV_WRITE_FILE_DATA FileData; + EFI_DISK_IO_PROTOCOL *DiskIo; + + if (!FileHandleValid (File)) { + return EFI_INVALID_PARAMETER; + } + + switch (File->Type) { + case EfiOpenMemoryBuffer: + if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) { + return EFI_END_OF_FILE; + } + + CopyMem (File->Buffer + File->CurrentPosition, Buffer, *BufferSize); + File->CurrentPosition += *BufferSize; + Status = EFI_SUCCESS; + + case EfiOpenLoadFile: + // LoadFile device is read only be definition + Status = EFI_UNSUPPORTED; + + case EfiOpenFirmwareVolume: + if (File->FvSectionType != EFI_SECTION_ALL) { + // Writes not support to a specific section. You have to update entire file + return EFI_UNSUPPORTED; + } + + FileData.NameGuid = &(File->FvNameGuid); + FileData.Type = File->FvType; + FileData.FileAttributes = File->FvAttributes; + FileData.Buffer = Buffer; + FileData.BufferSize = (UINT32)*BufferSize; + Status = File->Fv->WriteFile (File->Fv, 1, EFI_FV_UNRELIABLE_WRITE, &FileData); + break; + + case EfiOpenFileSystem: + Status = File->FsFileHandle->Write (File->FsFileHandle, BufferSize, Buffer); + File->CurrentPosition += *BufferSize; + break; + + case EfiOpenBlockIo: + if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) { + return EFI_END_OF_FILE; + } + + Status = gBS->HandleProtocol (File->EfiHandle, &gEfiDiskIoProtocolGuid, (VOID **)&DiskIo); + if (!EFI_ERROR(Status)) { + Status = DiskIo->WriteDisk (DiskIo, File->FsBlockIoMedia.MediaId, File->DiskOffset + File->CurrentPosition, *BufferSize, Buffer); + } + File->CurrentPosition += *BufferSize; + break; + + case EfiOpenTftp: + // Cache the file if it hasn't been cached yet. + if (File->IsBufferValid == FALSE) { + Status = CacheTftpFile(File); + if (EFI_ERROR(Status)) { + return Status; + } + } + + // Don't overwrite the buffer + if ((File->CurrentPosition + *BufferSize) > File->MaxPosition) { + UINT8 *TempBuffer; + + TempBuffer = File->Buffer; + + File->Buffer = AllocatePool (File->CurrentPosition + *BufferSize); + if (File->Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (File->Buffer, TempBuffer, File->Size); + + FreePool (TempBuffer); + + File->Size = File->CurrentPosition + *BufferSize; + File->MaxPosition = File->Size; + } + + // Copy in the requested data + CopyMem (File->Buffer + File->CurrentPosition, Buffer, *BufferSize); + File->CurrentPosition += *BufferSize; + + // Mark the file dirty + File->IsDirty = TRUE; + + Status = EFI_SUCCESS; + break; + + default: + Status = EFI_INVALID_PARAMETER; + }; + + return Status; +} + diff --git a/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf new file mode 100644 index 0000000000..a69fb0c423 --- /dev/null +++ b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.inf @@ -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
diff --git a/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.c b/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.c new file mode 100644 index 0000000000..ef5a2f2a7f --- /dev/null +++ b/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.c @@ -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++;
+ }
+}
+
+
+
+
diff --git a/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf b/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf new file mode 100644 index 0000000000..42a7caaa91 --- /dev/null +++ b/EmbeddedPkg/Library/GdbSerialDebugPortLib/GdbSerialDebugPortLib.inf @@ -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
diff --git a/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.c b/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.c new file mode 100644 index 0000000000..62d8636456 --- /dev/null +++ b/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.c @@ -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++;
+ }
+}
+
+
+
+
diff --git a/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf b/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf new file mode 100644 index 0000000000..0c8d0e6a69 --- /dev/null +++ b/EmbeddedPkg/Library/GdbSerialLib/GdbSerialLib.inf @@ -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
diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Capsule.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Capsule.c new file mode 100644 index 0000000000..cbc48b2b0c --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Capsule.c @@ -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
+ )
+{
+}
diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Mtc.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Mtc.c new file mode 100644 index 0000000000..8e8f2dbf24 --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Mtc.c @@ -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);
+}
+
diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/ReportStatusCode.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/ReportStatusCode.c new file mode 100644 index 0000000000..f1953a89d8 --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/ReportStatusCode.c @@ -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;
+}
+
+
+
diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Reset.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Reset.c new file mode 100644 index 0000000000..8671971a22 --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Reset.c @@ -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);
+}
+
diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Rtc.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Rtc.c new file mode 100644 index 0000000000..bb87ba82be --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Rtc.c @@ -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;
+}
+
+
diff --git a/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c new file mode 100644 index 0000000000..d96a44304a --- /dev/null +++ b/EmbeddedPkg/Library/HalRuntimeServicesExampleLib/Variable.c @@ -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;
+}
+
diff --git a/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.c b/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.c new file mode 100644 index 0000000000..b635fa0d9e --- /dev/null +++ b/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.c @@ -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;
+}
diff --git a/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf b/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf new file mode 100644 index 0000000000..bffe5b250a --- /dev/null +++ b/EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf @@ -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
diff --git a/EmbeddedPkg/Library/PrePiLib/FwVol.c b/EmbeddedPkg/Library/PrePiLib/FwVol.c new file mode 100644 index 0000000000..4a9e24683f --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/FwVol.c @@ -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; +} + + diff --git a/EmbeddedPkg/Library/PrePiLib/Hob.c b/EmbeddedPkg/Library/PrePiLib/Hob.c new file mode 100644 index 0000000000..3c6574282c --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/Hob.c @@ -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)); +} + + diff --git a/EmbeddedPkg/Library/PrePiLib/Memory.c b/EmbeddedPkg/Library/PrePiLib/Memory.c new file mode 100644 index 0000000000..209c71b42f --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/Memory.c @@ -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); + } +} + + + diff --git a/EmbeddedPkg/Library/PrePiLib/PrePi.h b/EmbeddedPkg/Library/PrePiLib/PrePi.h new file mode 100644 index 0000000000..dc3ef48614 --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/PrePi.h @@ -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 diff --git a/EmbeddedPkg/Library/PrePiLib/PrePiLib.c b/EmbeddedPkg/Library/PrePiLib/PrePiLib.c new file mode 100644 index 0000000000..f92be0fea3 --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/PrePiLib.c @@ -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; +} + + diff --git a/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf b/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf new file mode 100644 index 0000000000..278ee44722 --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/PrePiLib.inf @@ -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
diff --git a/EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c b/EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c new file mode 100644 index 0000000000..8833567fe5 --- /dev/null +++ b/EmbeddedPkg/Library/PrePiLib/ReportStatusCode.c @@ -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 *)); +} + diff --git a/EmbeddedPkg/Library/SemiHostingDebugLib/DebugLib.c b/EmbeddedPkg/Library/SemiHostingDebugLib/DebugLib.c new file mode 100644 index 0000000000..61e3aac3c2 --- /dev/null +++ b/EmbeddedPkg/Library/SemiHostingDebugLib/DebugLib.c @@ -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);
+}
diff --git a/EmbeddedPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf b/EmbeddedPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf new file mode 100644 index 0000000000..683f03f2f3 --- /dev/null +++ b/EmbeddedPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf @@ -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
+
diff --git a/EmbeddedPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf b/EmbeddedPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf new file mode 100644 index 0000000000..c0a540342a --- /dev/null +++ b/EmbeddedPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf @@ -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
diff --git a/EmbeddedPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c b/EmbeddedPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c new file mode 100644 index 0000000000..cadeb73731 --- /dev/null +++ b/EmbeddedPkg/Library/SemiHostingSerialPortLib/SerialPortLib.c @@ -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 ();
+}
+
diff --git a/EmbeddedPkg/Library/TemplateRealTimeClockLib/RealTimeClockLib.c b/EmbeddedPkg/Library/TemplateRealTimeClockLib/RealTimeClockLib.c new file mode 100644 index 0000000000..6a5acad376 --- /dev/null +++ b/EmbeddedPkg/Library/TemplateRealTimeClockLib/RealTimeClockLib.c @@ -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;
+}
+
+
+
diff --git a/EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf b/EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf new file mode 100644 index 0000000000..b9f39dd380 --- /dev/null +++ b/EmbeddedPkg/Library/TemplateRealTimeClockLib/TemplateRealTimeClockLib.inf @@ -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
+
\ No newline at end of file diff --git a/EmbeddedPkg/Library/TemplateResetSystemLib/ResetSystemLib.c b/EmbeddedPkg/Library/TemplateResetSystemLib/ResetSystemLib.c new file mode 100644 index 0000000000..fe02f9863f --- /dev/null +++ b/EmbeddedPkg/Library/TemplateResetSystemLib/ResetSystemLib.c @@ -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;
+}
+
diff --git a/EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf b/EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf new file mode 100644 index 0000000000..4b6fa5bb1a --- /dev/null +++ b/EmbeddedPkg/Library/TemplateResetSystemLib/TemplateResetSystemLib.inf @@ -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
\ No newline at end of file diff --git a/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c new file mode 100644 index 0000000000..98087f9dc0 --- /dev/null +++ b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.c @@ -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;
+}
+
diff --git a/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf new file mode 100644 index 0000000000..e2a994b63e --- /dev/null +++ b/EmbeddedPkg/Library/TemplateSerialPortLib/TemplateSerialPortLib.inf @@ -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
+
diff --git a/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c new file mode 100644 index 0000000000..b93626a6fb --- /dev/null +++ b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c @@ -0,0 +1,158 @@ +/** @file
+ Implement EFI RealTimeClock runtime services via RTC Lib.
+
+ Currently this driver does not support runtime virtual calling.
+
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/RealTimeClockLib.h>
+#include <Protocol/RealTimeClock.h>
+
+EFI_HANDLE mHandle = NULL;
+
+
+
+/**
+ Returns the current time and date information, and the time-keeping capabilities
+ of the hardware platform.
+
+ @param Time A pointer to storage to receive a snapshot of the current time.
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
+ device's capabilities.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER Time is NULL.
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTime (
+ OUT EFI_TIME *Time,
+ OUT EFI_TIME_CAPABILITIES *Capabilities
+ )
+{
+ return LibGetTime (Time, Capabilities);
+}
+
+
+
+/**
+ Sets the current local time and date information.
+
+ @param Time A pointer to the current time.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+SetTime (
+ IN EFI_TIME *Time
+ )
+{
+ return LibSetTime (Time);
+}
+
+
+/**
+ Returns the current wakeup alarm clock setting.
+
+ @param Enabled Indicates if the alarm is currently enabled or disabled.
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.
+ @param Time The current alarm setting.
+
+ @retval EFI_SUCCESS The alarm settings were returned.
+ @retval EFI_INVALID_PARAMETER Any parameter is NULL.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+GetWakeupTime (
+ OUT BOOLEAN *Enabled,
+ OUT BOOLEAN *Pending,
+ OUT EFI_TIME *Time
+ )
+{
+ return LibGetWakeupTime (Enabled, Pending, Time);
+}
+
+
+/**
+ Sets the system wakeup alarm clock time.
+
+ @param Enabled Enable or disable the wakeup alarm.
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.
+
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
+ Enable is FALSE, then the wakeup alarm was disabled.
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
+
+**/
+EFI_STATUS
+EFIAPI
+SetWakeupTime (
+ IN BOOLEAN Enabled,
+ OUT EFI_TIME *Time
+ )
+{
+ return LibSetWakeupTime (Enabled, Time);
+}
+
+
+
+/**
+ This is the declaration of an EFI image entry point. This can be the entry point to an application
+ written to this specification, an EFI boot service driver, or an EFI runtime driver.
+
+ @param ImageHandle Handle that identifies the loaded image.
+ @param SystemTable System Table for this image.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeRealTimeClock (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ LibRtcInitialize (ImageHandle, SystemTable);
+
+ SystemTable->RuntimeServices->GetTime = GetTime;
+ SystemTable->RuntimeServices->SetTime = SetTime;
+ SystemTable->RuntimeServices->GetWakeupTime = GetWakeupTime;
+ SystemTable->RuntimeServices->SetWakeupTime = SetWakeupTime;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiRealTimeClockArchProtocolGuid,
+ NULL,
+ NULL
+ );
+
+ return Status;
+}
+
diff --git a/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf new file mode 100644 index 0000000000..f0afceeb65 --- /dev/null +++ b/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf @@ -0,0 +1,45 @@ +#%HEADER%
+#/** @file
+# NT Emulation Reset Architectural Protocol Driver as defined in TIANO
+#
+# This Reset module simulates system reset by process exit on NT.
+# Copyright (c) 2006 - 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = RealTimeClock
+ FILE_GUID = B336F62D-4135-4A55-AE4E-4971BBF0885D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeRealTimeClock
+
+[Sources.common]
+ RealTimeClock.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ DebugLib
+ RealTimeClockLib
+
+[Protocols]
+ gEfiRealTimeClockArchProtocolGuid
+
+[Depex]
+ TRUE
+
diff --git a/EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf b/EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf new file mode 100644 index 0000000000..956aab709a --- /dev/null +++ b/EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf @@ -0,0 +1,51 @@ +#%HEADER%
+#/** @file
+# NT Emulation Reset Architectural Protocol Driver as defined in TIANO
+#
+# This Reset module simulates system reset by process exit on NT.
+# Copyright (c) 2006 - 2007, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Reset
+ FILE_GUID = 16036A73-E8EF-46D0-953C-9B8E96527D13
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeReset
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32
+#
+
+[Sources.common]
+ reset.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ DebugLib
+ EfiResetSystemLib
+
+[Protocols]
+ gEfiResetArchProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[Depex]
+ TRUE
+
diff --git a/EmbeddedPkg/ResetRuntimeDxe/reset.c b/EmbeddedPkg/ResetRuntimeDxe/reset.c new file mode 100644 index 0000000000..3327b8d1ec --- /dev/null +++ b/EmbeddedPkg/ResetRuntimeDxe/reset.c @@ -0,0 +1,74 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Protocol/Reset.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/EfiResetSystemLib.h>
+
+
+/**
+ Resets the entire platform.
+
+ @param ResetType The type of reset to perform.
+ @param ResetStatus The status code for the reset.
+ @param DataSize The size, in bytes, of WatchdogData.
+ @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or
+ EfiResetShutdown the data buffer starts with a Null-terminated
+ Unicode string, optionally followed by additional binary data.
+
+**/
+VOID
+EFIAPI
+ResetSystemViaLib (
+ IN EFI_RESET_TYPE ResetType,
+ IN EFI_STATUS ResetStatus,
+ IN UINTN DataSize,
+ IN VOID *ResetData OPTIONAL
+ )
+{
+ LibResetSystem (ResetType, ResetStatus, DataSize, ResetData);
+ return;
+}
+
+
+
+EFI_STATUS
+EFIAPI
+InitializeReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ LibInitializeResetSystem (ImageHandle, SystemTable);
+
+ SystemTable->RuntimeServices->ResetSystem = ResetSystemViaLib;
+
+ Handle = NULL;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiResetArchProtocolGuid,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/EmbeddedPkg/SerialDxe/SerialDxe.inf b/EmbeddedPkg/SerialDxe/SerialDxe.inf new file mode 100644 index 0000000000..29c0aa8c2a --- /dev/null +++ b/EmbeddedPkg/SerialDxe/SerialDxe.inf @@ -0,0 +1,54 @@ +#%HEADER%
+#/** @file
+#
+# Component discription file for Bds module
+#
+# Copyright (c) 2008, Intel Corporation. <BR>
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SerialDxe
+ FILE_GUID = D3987D4B-971A-435F-8CAF-4967EB627241
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = SerialDxeInitialize
+
+
+[Sources.common]
+ SerialIo.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ ReportStatusCodeLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ UefiDriverEntryPoint
+ SerialPortLib
+
+[Guids]
+
+
+[Protocols]
+ gEfiSerialIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+
+
+[Depex]
+ TRUE
diff --git a/EmbeddedPkg/SerialDxe/SerialIo.c b/EmbeddedPkg/SerialDxe/SerialIo.c new file mode 100644 index 0000000000..aa9653bcf3 --- /dev/null +++ b/EmbeddedPkg/SerialDxe/SerialIo.c @@ -0,0 +1,258 @@ +/** @file
+ Serial IO Abstraction for GDB stub. This allows an EFI consoles that shows up on the system
+ running GDB. One consle for error information and another console for user input/output.
+
+ Basic packet format is $packet-data#checksum. So every comand has 4 bytes of overhead: $,
+ #, 0, 0. The 0 and 0 are the ascii characters for the checksum.
+
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SerialPortLib.h>
+
+#include <Protocol/SerialIo.h>
+
+/**
+ Reset the serial device.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The serial device could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+SerialReset (
+ IN EFI_SERIAL_IO_PROTOCOL *This
+ )
+{
+ SerialPortInitialize ();
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Sets the baud rate, receive FIFO depth, transmit/receice time out, parity,
+ data buts, and stop bits on a serial device.
+
+ @param This Protocol instance pointer.
+ @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the
+ device's default interface speed.
+ @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the
+ serial interface. A ReceiveFifoDepth value of 0 will use
+ the device's dfault FIFO depth.
+ @param Timeout The requested time out for a single character in microseconds.
+ This timeout applies to both the transmit and receive side of the
+ interface. A Timeout value of 0 will use the device's default time
+ out value.
+ @param Parity The type of parity to use on this serial device. A Parity value of
+ DefaultParity will use the device's default parity value.
+ @param DataBits The number of data bits to use on the serial device. A DataBits
+ vaule of 0 will use the device's default data bit setting.
+ @param StopBits The number of stop bits to use on this serial device. A StopBits
+ value of DefaultStopBits will use the device's default number of
+ stop bits.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The serial device could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+SerialSetAttributes (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT64 BaudRate,
+ IN UINT32 ReceiveFifoDepth,
+ IN UINT32 Timeout,
+ IN EFI_PARITY_TYPE Parity,
+ IN UINT8 DataBits,
+ IN EFI_STOP_BITS_TYPE StopBits
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Set the control bits on a serial device
+
+ @param This Protocol instance pointer.
+ @param Control Set the bits of Control that are settable.
+
+ @retval EFI_SUCCESS The new control bits were set on the serial device.
+ @retval EFI_UNSUPPORTED The serial device does not support this operation.
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+EFI_STATUS
+EFIAPI
+SerialSetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT32 Control
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Retrieves the status of thecontrol bits on a serial device
+
+ @param This Protocol instance pointer.
+ @param Control A pointer to return the current Control signals from the serial device.
+
+ @retval EFI_SUCCESS The control bits were read from the serial device.
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly.
+
+**/
+EFI_STATUS
+EFIAPI
+SerialGetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ OUT UINT32 *Control
+ )
+{
+ if (SerialPortPoll ()) {
+ // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY
+ *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ } else {
+ *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ }
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Writes data to a serial device.
+
+ @param This Protocol instance pointer.
+ @param BufferSize On input, the size of the Buffer. On output, the amount of
+ data actually written.
+ @param Buffer The buffer of data to write
+
+ @retval EFI_SUCCESS The data was written.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_TIMEOUT The data write was stopped due to a timeout.
+
+**/
+EFI_STATUS
+EFIAPI
+SerialWrite (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ UINTN Count;
+
+ Count = SerialPortWrite (Buffer, *BufferSize);
+ *BufferSize = Count;
+ return (Count == 0) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
+}
+
+/**
+ Writes data to a serial device.
+
+ @param This Protocol instance pointer.
+ @param BufferSize On input, the size of the Buffer. On output, the amount of
+ data returned in Buffer.
+ @param Buffer The buffer to return the data into.
+
+ @retval EFI_SUCCESS The data was read.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_TIMEOUT The data write was stopped due to a timeout.
+
+**/
+
+EFI_STATUS
+EFIAPI
+SerialRead (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ UINTN Count;
+
+ Count = SerialPortWrite (Buffer, *BufferSize);
+ *BufferSize = Count;
+ return (Count == 0) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
+}
+
+
+EFI_HANDLE gHandle = NULL;
+
+//
+// Template used to initailize the GDB Serial IO protocols
+//
+EFI_SERIAL_IO_MODE gSerialIoMode = {
+ 0, // ControlMask
+ 0, // Timeout
+ 0, // BaudRate
+ 1, // RceiveFifoDepth
+ 0, // DataBits
+ 0, // Parity
+ 0 // StopBits
+};
+
+
+EFI_SERIAL_IO_PROTOCOL gSerialIoTemplate = {
+ SERIAL_IO_INTERFACE_REVISION,
+ SerialReset,
+ SerialSetAttributes,
+ SerialSetControl,
+ SerialGetControl,
+ SerialWrite,
+ SerialRead,
+ &gSerialIoMode
+};
+
+
+/**
+ Initialize the state information for the Serial Io Protocol
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+EFIAPI
+SerialDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+
+ // Make a new handle with Serial IO protocol and its device path on it.
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gHandle,
+ &gEfiSerialIoProtocolGuid, &gSerialIoTemplate,
+ &gEfiDevicePathProtocolGuid, NULL, // BugBug: Need a device path
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOut.c b/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOut.c new file mode 100644 index 0000000000..f491de6e95 --- /dev/null +++ b/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOut.c @@ -0,0 +1,671 @@ +/** @file
+ Simple Console that sits on a SerialLib.
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+/*
+ Symbols used in table below
+===========================
+ ESC = 0x1B
+ CSI = 0x9B
+ DEL = 0x7f
+ ^ = CTRL
+
++=========+======+===========+==========+==========+
+| | EFI | UEFI 2.0 | | |
+| | Scan | | VT100+ | |
+| KEY | Code | PC ANSI | VTUTF8 | VT100 |
++=========+======+===========+==========+==========+
+| NULL | 0x00 | | | |
+| UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
+| DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
+| RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
+| LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
+| HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
+| END | 0x06 | ESC [ F | ESC k | ESC [ K |
+| INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
+| | | ESC [ L | | ESC [ L |
+| DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
+| PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
+| | | | | ESC [ ? |
+| PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
+| | | | | ESC [ / |
+| F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
+| F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
+| F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
+| F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
+| F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
+| F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
+| F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
+| F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
+| F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
+| F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
+| Escape | 0x17 | ESC | ESC | ESC |
+| F11 | 0x15 | | ESC ! | |
+| F12 | 0x16 | | ESC @ | |
++=========+======+===========+==========+==========+
+
+*/
+
+#include <PiDxe.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SerialPortLib.h>
+
+#include <Protocol/SerialIo.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextOut.h>
+
+
+#define MODE0_COLUMN_COUNT 80
+#define MODE0_ROW_COUNT 25
+
+
+EFI_STATUS
+EFIAPI
+TextInReset(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+
+EFI_STATUS
+EFIAPI
+ReadKeyStroke(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+
+EFI_STATUS
+EFIAPI
+TextOutReset(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+CHAR8 *
+EFIAPI
+SafeUnicodeStrToAsciiStr (
+ IN CONST CHAR16 *Source,
+ OUT CHAR8 *Destination
+ );
+
+EFI_STATUS
+EFIAPI
+OutputString (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ );
+
+
+EFI_STATUS
+EFIAPI
+TestString (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ );
+
+
+EFI_STATUS
+EFIAPI
+QueryMode (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber,
+ OUT UINTN *Columns,
+ OUT UINTN *Rows
+ );
+
+
+EFI_STATUS
+EFIAPI
+SetMode(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ );
+
+
+EFI_STATUS
+EFIAPI
+SetAttribute(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+ );
+
+
+EFI_STATUS
+EFIAPI
+ClearScreen (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+ );
+
+
+EFI_STATUS
+EFIAPI
+SetCursorPosition (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ );
+
+
+EFI_STATUS
+EFIAPI
+EnableCursor (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Enable
+ );
+
+
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn = {
+ TextInReset,
+ ReadKeyStroke,
+ NULL
+};
+
+ EFI_SIMPLE_TEXT_OUTPUT_MODE mSimpleTextOutMode = {
+ 1,
+ 0,
+ EFI_TEXT_ATTR( EFI_LIGHTGRAY, EFI_BLACK ),
+ 0,
+ 0,
+ TRUE
+};
+
+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mSimpleTextOut = {
+ TextOutReset,
+ OutputString,
+ TestString,
+ QueryMode,
+ SetMode,
+ SetAttribute,
+ ClearScreen,
+ SetCursorPosition,
+ EnableCursor,
+ &mSimpleTextOutMode
+};
+
+ EFI_HANDLE mInstallHandle = NULL;
+
+
+
+BOOLEAN
+TextOutIsValidAscii (
+ IN CHAR16 Ascii
+ )
+{
+ //
+ // valid ASCII code lies in the extent of 0x20 - 0x7F
+ //
+ if ((Ascii >= 0x20) && (Ascii <= 0x7F)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+BOOLEAN
+TextOutIsValidEfiCntlChar (
+ IN CHAR16 Char
+ )
+{
+ //
+ // only support four control characters.
+ //
+ if (Char == CHAR_NULL ||
+ Char == CHAR_BACKSPACE ||
+ Char == CHAR_LINEFEED ||
+ Char == CHAR_CARRIAGE_RETURN ||
+ Char == CHAR_TAB ) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+VOID
+EFIAPI
+WaitForKeyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ if (SerialPortPoll ()) {
+ gBS->SignalEvent (Event);
+ }
+}
+
+
+EFI_STATUS
+EFIAPI
+TextInReset (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+ReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ )
+{
+ CHAR8 Char;
+
+ SerialPortRead ((UINT8 *)&Char, 1);
+
+ //
+ // Check for ESC sequence. This code is not techincally correct VT100 code.
+ // An illegal ESC sequence represents an ESC and the characters that follow.
+ // This code will eat one or two chars after an escape. This is done to
+ // prevent some complex FIFOing of the data. It is good enough to get
+ // the arrow and delete keys working
+ //
+ Key->UnicodeChar = 0;
+ Key->ScanCode = SCAN_NULL;
+ if (Char == 0x1b) {
+ SerialPortRead ((UINT8 *)&Char, 1);
+ if (Char == '[') {
+ SerialPortRead ((UINT8 *)&Char, 1);
+ switch (Char) {
+ case 'A':
+ Key->ScanCode = SCAN_UP;
+ break;
+ case 'B':
+ Key->ScanCode = SCAN_DOWN;
+ break;
+ case 'C':
+ Key->ScanCode = SCAN_RIGHT;
+ break;
+ case 'D':
+ Key->ScanCode = SCAN_LEFT;
+ break;
+ case 'H':
+ Key->ScanCode = SCAN_HOME;
+ break;
+ case 'K':
+ case 'F': // PC ANSI
+ Key->ScanCode = SCAN_END;
+ break;
+ case '@':
+ case 'L':
+ Key->ScanCode = SCAN_INSERT;
+ break;
+ case 'P':
+ case 'X': // PC ANSI
+ Key->ScanCode = SCAN_DELETE;
+ break;
+ case 'U':
+ case '/':
+ case 'G': // PC ANSI
+ Key->ScanCode = SCAN_PAGE_DOWN;
+ break;
+ case 'V':
+ case '?':
+ case 'I': // PC ANSI
+ Key->ScanCode = SCAN_PAGE_UP;
+ break;
+
+ // PCANSI that does not conflict with VT100
+ case 'M':
+ Key->ScanCode = SCAN_F1;
+ break;
+ case 'N':
+ Key->ScanCode = SCAN_F2;
+ break;
+ case 'O':
+ Key->ScanCode = SCAN_F3;
+ break;
+ case 'Q':
+ Key->ScanCode = SCAN_F5;
+ break;
+ case 'R':
+ Key->ScanCode = SCAN_F6;
+ break;
+ case 'S':
+ Key->ScanCode = SCAN_F7;
+ break;
+ case 'T':
+ Key->ScanCode = SCAN_F8;
+ break;
+
+ default:
+ Key->UnicodeChar = Char;
+ break;
+ }
+ } else if (Char == '0') {
+ SerialPortRead ((UINT8 *)&Char, 1);
+ switch (Char) {
+ case 'P':
+ Key->ScanCode = SCAN_F1;
+ break;
+ case 'Q':
+ Key->ScanCode = SCAN_F2;
+ break;
+ case 'w':
+ Key->ScanCode = SCAN_F3;
+ break;
+ case 'x':
+ Key->ScanCode = SCAN_F4;
+ break;
+ case 't':
+ Key->ScanCode = SCAN_F5;
+ break;
+ case 'u':
+ Key->ScanCode = SCAN_F6;
+ break;
+ case 'q':
+ Key->ScanCode = SCAN_F7;
+ break;
+ case 'r':
+ Key->ScanCode = SCAN_F8;
+ break;
+ case 'p':
+ Key->ScanCode = SCAN_F9;
+ break;
+ case 'm':
+ Key->ScanCode = SCAN_F10;
+ break;
+ default :
+ break;
+ }
+ }
+ } else if (Char < ' ') {
+ if ((Char == CHAR_BACKSPACE) ||
+ (Char == CHAR_TAB) ||
+ (Char == CHAR_LINEFEED) ||
+ (Char == CHAR_CARRIAGE_RETURN)) {
+ // Only let through EFI required control characters
+ Key->UnicodeChar = (CHAR16)Char;
+ }
+ } else if (Char == 0x7f) {
+ Key->ScanCode = SCAN_DELETE;
+ } else {
+ Key->UnicodeChar = (CHAR16)Char;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+TextOutReset (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EFI_STATUS Status;
+
+ This->SetAttribute(
+ This,
+ EFI_TEXT_ATTR(This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)
+ );
+
+ Status = This->SetMode (This, 0);
+
+ return Status;
+}
+
+CHAR8 *
+EFIAPI
+SafeUnicodeStrToAsciiStr (
+ IN CONST CHAR16 *Source,
+ OUT CHAR8 *Destination
+ )
+{
+ CHAR8 *ReturnValue;
+
+ ASSERT (Destination != NULL);
+
+ //
+ // ASSERT if Source is long than PcdMaximumUnicodeStringLength.
+ // Length tests are performed inside StrLen().
+ //
+ ASSERT (StrSize (Source) != 0);
+
+ //
+ // Source and Destination should not overlap
+ //
+ ASSERT ((UINTN) ((CHAR16 *) Destination - Source) > StrLen (Source));
+ ASSERT ((UINTN) ((CHAR8 *) Source - Destination) > StrLen (Source));
+
+
+ ReturnValue = Destination;
+ while (*Source != '\0') {
+ //
+ // If any non-ascii characters in Source then replace it with '?'.
+ //
+ if (*Source < 0x80) {
+ *Destination = (CHAR8) *Source;
+ } else {
+ *Destination = '?';
+
+ //Surrogate pair check.
+ if ((*Source >= 0xD800) && (*Source <= 0xDFFF)) {
+ Source++;
+ }
+ }
+
+ Destination++;
+ Source++;
+ }
+
+ *Destination = '\0';
+
+ //
+ // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength.
+ // Length tests are performed inside AsciiStrLen().
+ //
+ ASSERT (AsciiStrSize (ReturnValue) != 0);
+
+ return ReturnValue;
+}
+
+EFI_STATUS
+EFIAPI
+OutputString (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ )
+{
+ UINTN Size = StrLen(String) + 1;
+ CHAR8 *OutputString = AllocatePool(Size);
+
+ //If there is any non-ascii characters in String buffer then replace it with '?'
+ //Eventually, UnicodeStrToAsciiStr API should be fixed.
+ SafeUnicodeStrToAsciiStr(String, OutputString);
+ SerialPortWrite ((UINT8 *)OutputString, Size - 1);
+
+ FreePool(OutputString);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+TestString (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *String
+ )
+{
+ CHAR8 Character;
+
+ for ( ; *String != CHAR_NULL; String++) {
+ Character = (CHAR8)*String;
+ if (!(TextOutIsValidAscii (Character) || TextOutIsValidEfiCntlChar (Character))) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+QueryMode (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber,
+ OUT UINTN *Columns,
+ OUT UINTN *Rows
+ )
+{
+ if (This->Mode->MaxMode > 1) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (ModeNumber == 0) {
+ *Columns = MODE0_COLUMN_COUNT;
+ *Rows = MODE0_ROW_COUNT;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+SetMode (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ )
+{
+ if (ModeNumber != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ This->Mode->Mode = 0;
+ This->ClearScreen (This);
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+SetAttribute(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+ )
+{
+ This->Mode->Attribute = (INT32)Attribute;
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+ClearScreen (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+
+ Status = This->SetCursorPosition (This, 0, 0);
+ return Status;
+}
+
+
+EFI_STATUS
+EFIAPI
+SetCursorPosition (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ )
+{
+ EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
+ EFI_STATUS Status;
+ UINTN MaxColumn;
+ UINTN MaxRow;
+
+ Mode = This->Mode;
+
+ Status = This->QueryMode(
+ This,
+ Mode->Mode,
+ &MaxColumn,
+ &MaxRow
+ );
+ if (EFI_ERROR(Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((Column >= MaxColumn) || (Row >= MaxRow)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Mode->CursorColumn = (INT32)Column;
+ Mode->CursorRow = (INT32)Row;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+EnableCursor (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Enable
+ )
+{
+ if (!Enable) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+SimpleTextInOutEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ WaitForKeyEvent,
+ NULL,
+ &mSimpleTextIn.WaitForKey
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->InstallMultipleProtocolInterfaces(
+ &mInstallHandle,
+ &gEfiSimpleTextInProtocolGuid, &mSimpleTextIn,
+ &gEfiSimpleTextOutProtocolGuid, &mSimpleTextOut,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ gST->ConOut = &mSimpleTextOut;
+ gST->ConIn = &mSimpleTextIn;
+ }
+
+ return Status;
+}
diff --git a/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf b/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf new file mode 100644 index 0000000000..17821d62f7 --- /dev/null +++ b/EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOutSerial.inf @@ -0,0 +1,56 @@ +#%HEADER%
+#/** @file
+#
+# Component discription file for Bds module
+#
+# Copyright (c) 2008, Intel Corporation. <BR>
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SimpleTextInOutSerial
+ FILE_GUID = 6696936D-3637-467C-87CB-14EA8248948C
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = SimpleTextInOutEntryPoint
+
+
+[Sources.common]
+ SimpleTextInOut.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ ReportStatusCodeLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ UefiDriverEntryPoint
+ SerialPortLib
+
+[Guids]
+
+
+[Protocols]
+ gEfiSimpleTextInProtocolGuid
+ gEfiSimpleTextOutProtocolGuid
+ gEfiSerialIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+
+[depex]
+ TRUE
diff --git a/EmbeddedPkg/TemplateBds/BdsEntry.c b/EmbeddedPkg/TemplateBds/BdsEntry.c new file mode 100644 index 0000000000..dcdf499d20 --- /dev/null +++ b/EmbeddedPkg/TemplateBds/BdsEntry.c @@ -0,0 +1,183 @@ +/** @file
+ The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements
+ of the UEFI specification as it is designed to implement an embedded systmes
+ propriatary boot scheme.
+
+ This template assume a DXE driver produces a SerialIo protocol not using the EFI
+ driver module and it will attempt to connect a console on top of this.
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BdsEntry.h"
+
+
+BOOLEAN gConsolePresent = FALSE;
+
+
+EFI_HANDLE mBdsImageHandle = NULL;
+EFI_BDS_ARCH_PROTOCOL gBdsProtocol = {
+ BdsEntry,
+};
+
+
+
+
+/**
+ This function uses policy data from the platform to determine what operating
+ system or system utility should be loaded and invoked. This function call
+ also optionally make the use of user input to determine the operating system
+ or system utility to be loaded and invoked. When the DXE Core has dispatched
+ all the drivers on the dispatch queue, this function is called. This
+ function will attempt to connect the boot devices required to load and invoke
+ the selected operating system or system utility. During this process,
+ additional firmware volumes may be discovered that may contain addition DXE
+ drivers that can be dispatched by the DXE Core. If a boot device cannot be
+ fully connected, this function calls the DXE Service Dispatch() to allow the
+ DXE drivers from any newly discovered firmware volumes to be dispatched.
+ Then the boot device connection can be attempted again. If the same boot
+ device connection operation fails twice in a row, then that boot device has
+ failed, and should be skipped. This function should never return.
+
+ @param This The EFI_BDS_ARCH_PROTOCOL instance.
+
+ @return None.
+
+**/
+VOID
+EFIAPI
+BdsEntry (
+ IN EFI_BDS_ARCH_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ UINTN NoHandles;
+ EFI_HANDLE *Buffer;
+ UINTN Index;
+ EFI_HANDLE FvHandle;
+ EFI_GUID *NameGuid;
+
+ //
+ // This code assumes that a DXE driver produces a SerialIo protocol not following the EFI
+ // driver model. At a minimum we need to connect an EFI driver model terminal driver on top
+ // of the serial driver.
+ //
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Buffer);
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < NoHandles; Index++) {
+ // For every Serial IO protocol in the system connect EFI drivers to it.
+ // This should cause the terminal driver to bind to the Serial IO protocol and produce a
+ // child handle that produces SimpleTextOut & SImpleTextIn protocols
+ gBS->ConnectController (Buffer[Index], NULL, NULL, TRUE);
+ }
+
+ FreePool (Buffer);
+ }
+
+ //
+ // Now we need to setup the EFI System Table with information about the console devices.
+ // This code is normally in the console spliter driver on platforms that support multiple
+ // consoles at the same time
+ //
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextOutProtocolGuid, NULL, &NoHandles, &Buffer);
+ if (!EFI_ERROR (Status)) {
+ // Use the first SimpleTextOut we find and update the EFI System Table
+ gST->ConsoleOutHandle = Buffer[0];
+ gST->StandardErrorHandle = Buffer[0];
+ Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextOutProtocolGuid, (VOID **)&gST->ConOut);
+ ASSERT_EFI_ERROR (Status);
+
+ gST->StdErr = gST->ConOut;
+
+ FreePool (Buffer);
+
+ gConsolePresent = TRUE;
+ }
+
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextInProtocolGuid, NULL, &NoHandles, &Buffer);
+ if (!EFI_ERROR (Status)) {
+ // Use the first SimpleTextIn we find and update the EFI System Table
+ gST->ConsoleInHandle = Buffer[0];
+ Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextInProtocolGuid, (VOID **)&gST->ConIn);
+ ASSERT_EFI_ERROR (Status);
+
+ FreePool (Buffer);
+ }
+
+ //
+ // We now have EFI Consoles up and running. Print () will work now. DEBUG () and ASSERT () worked
+ // prior to this point as they were configured to use a more primative output scheme.
+ //
+
+
+ //
+ // Platform specific stuff goes here
+ //
+
+
+ //
+ // Normal UEFI behavior is to process Globally Defined Variables as defined in Chapter 3
+ // (Boot Manager) of the UEFI specification. For this embedded system we don't do this.
+ //
+
+ //
+ // Search all the FVs for an application with a UI Section of Ebl. A .FDF file can be used
+ // to control the names of UI sections in an FV.
+ //
+ Status = FindApplicationMatchingUiSection (L"Ebl", &FvHandle, &NameGuid);
+ if (EFI_ERROR (Status)) {
+ //
+ // Just load the first application we find reguardless of name.
+ // This is the fallback path.
+ //
+ Status = FindApplicationMatchingUiSection (NULL, &FvHandle, &NameGuid);
+ // Nothing to boot
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = LoadPeCoffSectionFromFv (FvHandle, NameGuid);
+
+ //
+ // EFI does not define the bavior if all boot attemps fail and the last one returns.
+ // So we make a policy choice to reset the system since this BDS does not have a UI.
+ //
+ gRT->ResetSystem (EfiResetCold, Status, 0, NULL);
+
+ return ;
+}
+
+
+EFI_STATUS
+EFIAPI
+BdsInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mBdsImageHandle = ImageHandle;
+
+ //
+ // Install protocol interface
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mBdsImageHandle,
+ &gEfiBdsArchProtocolGuid, &gBdsProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
diff --git a/EmbeddedPkg/TemplateBds/BdsEntry.h b/EmbeddedPkg/TemplateBds/BdsEntry.h new file mode 100644 index 0000000000..31eb6d7d4e --- /dev/null +++ b/EmbeddedPkg/TemplateBds/BdsEntry.h @@ -0,0 +1,62 @@ +/** @file
+
+ Copyright (c) 2008-2009 Apple Inc. All rights reserved.<BR>
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __BDS_ENTRY_H__
+#define __BDS_ENTRY_H__
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/HobLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/Bds.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextOut.h>
+
+
+
+
+EFI_STATUS
+LoadPeCoffSectionFromFv (
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *NameGuid
+ );
+
+EFI_STATUS
+FindApplicationMatchingUiSection (
+ IN CHAR16 *UiString,
+ OUT EFI_HANDLE *FvHandle,
+ OUT EFI_GUID **NameGuid
+ );
+
+VOID
+EFIAPI
+BdsEntry (
+ IN EFI_BDS_ARCH_PROTOCOL *This
+ );
+
+#endif
+
diff --git a/EmbeddedPkg/TemplateBds/FirmwareVolume.c b/EmbeddedPkg/TemplateBds/FirmwareVolume.c new file mode 100644 index 0000000000..b6a2206a86 --- /dev/null +++ b/EmbeddedPkg/TemplateBds/FirmwareVolume.c @@ -0,0 +1,160 @@ +/** @file
+ The entry of the embedded BDS. This BDS does not follow the Boot Manager requirements
+ of the UEFI specification as it is designed to implement an embedded systmes
+ propriatary boot scheme.
+
+ This template assume a DXE driver produces a SerialIo protocol not using the EFI
+ driver module and it will attempt to connect a console on top of this.
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BdsEntry.h"
+
+
+EFI_STATUS
+FindApplicationMatchingUiSection (
+ IN CHAR16 *UiString,
+ OUT EFI_HANDLE *FvHandle,
+ OUT EFI_GUID **NameGuid
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS NextStatus;
+ UINTN NoHandles;
+ EFI_HANDLE *Buffer;
+ UINTN Index;
+ EFI_FV_FILETYPE FileType;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ VOID *Key;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN UiStringLen;
+ CHAR16 *UiSection;
+ UINT32 Authentication;
+
+
+ UiStringLen = 0;
+ if (UiString != NULL) {
+ UiStringLen = StrLen (UiString);
+ }
+
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Buffer);
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < NoHandles; Index++) {
+ Status = gBS->HandleProtocol (Buffer[Index], &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
+ if (!EFI_ERROR (Status)) {
+ Key = AllocatePool (Fv->KeySize);
+ FileType = EFI_FV_FILETYPE_APPLICATION;
+
+ do {
+ NextStatus = Fv->GetNextFile (Fv, Key, &FileType, *NameGuid, &Attributes, &Size);
+ if (!EFI_ERROR (NextStatus)) {
+ if (UiString == NULL) {
+ //
+ // If UiString is NULL match first application we find.
+ //
+ *FvHandle = Buffer[Index];
+ FreePool (Key);
+ return Status;
+ }
+
+ UiSection = NULL;
+ Status = Fv->ReadSection (
+ Fv,
+ *NameGuid,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ (VOID **)&UiSection,
+ &Size,
+ &Authentication
+ );
+ if (!EFI_ERROR (Status)) {
+ if (StrnCmp (UiString, UiSection, UiStringLen)) {
+ //
+ // We found a UiString match.
+ //
+ *FvHandle = Buffer[Index];
+ FreePool (Key);
+ FreePool (UiSection);
+ return Status;
+ }
+ FreePool (UiSection);
+ }
+ }
+ } while (!EFI_ERROR (NextStatus));
+
+ FreePool (Key);
+ }
+ }
+
+ FreePool (Buffer);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_DEVICE_PATH *
+FvFileDevicePath (
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *NameGuid
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH NewNode;
+
+ DevicePath = DevicePathFromHandle (FvHandle);
+
+ EfiInitializeFwVolDevicepathNode (&NewNode, NameGuid);
+
+ return AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&NewNode);
+}
+
+
+
+EFI_STATUS
+LoadPeCoffSectionFromFv (
+ IN EFI_HANDLE FvHandle,
+ IN EFI_GUID *NameGuid
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
+ VOID *Buffer;
+ UINTN BufferSize;
+ UINT32 Authentication;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HANDLE ImageHandle;
+
+ Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = Fv->ReadSection (Fv, NameGuid, EFI_SECTION_PE32, 0, &Buffer, &BufferSize, &Authentication);
+ if (!EFI_ERROR (Status)) {
+ DevicePath = FvFileDevicePath (FvHandle, NameGuid);
+ Status = gBS->LoadImage (TRUE, gImageHandle, DevicePath, Buffer, BufferSize, &ImageHandle);
+ if (!EFI_ERROR (Status)) {
+ // ExitData is NULL so we need to pass in a size of zero
+ BufferSize = 0;
+ Status = gBS->StartImage (ImageHandle, &BufferSize, NULL);
+ }
+
+ FreePool (Buffer);
+ }
+
+
+ return Status;
+}
+
diff --git a/EmbeddedPkg/TemplateBds/TemplateBds.inf b/EmbeddedPkg/TemplateBds/TemplateBds.inf new file mode 100644 index 0000000000..5a3c1b9801 --- /dev/null +++ b/EmbeddedPkg/TemplateBds/TemplateBds.inf @@ -0,0 +1,68 @@ +#%HEADER%
+#/** @file
+#
+# Component discription file for Bds module
+#
+# Copyright (c) 2008, Intel Corporation. <BR>
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TemplateBds
+ FILE_GUID = 3C85595C-70FD-447D-B0CB-7F6BBA9C9BEB
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = BdsInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ BdsEntry.c
+ FirmwareVolume.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DevicePathLib
+ BaseLib
+ HobLib
+ UefiRuntimeServicesTableLib
+ ReportStatusCodeLib
+ PerformanceLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ UefiDriverEntryPoint
+
+[Guids]
+
+
+[Protocols]
+ gEfiBdsArchProtocolGuid
+ gEfiSimpleTextInProtocolGuid
+ gEfiSimpleTextOutProtocolGuid
+ gEfiSerialIoProtocolGuid
+ gEfiDevicePathProtocolGuid
+ gEfiFirmwareVolume2ProtocolGuid
+
+[depex]
+ TRUE
diff --git a/EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c b/EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c new file mode 100644 index 0000000000..e32d47e123 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/Arm/Exception.c @@ -0,0 +1,250 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <CpuDxe.h>
+#include <Library/CacheMaintenanceLib.h>
+
+VOID
+ExceptionHandlersStart (
+ VOID
+ );
+
+VOID
+ExceptionHandlersEnd (
+ VOID
+ );
+
+VOID
+CommonExceptionEntry (
+ VOID
+ );
+
+VOID
+AsmCommonExceptionEntry (
+ VOID
+ );
+
+
+EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1];
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+RegisterInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType > MAX_ARM_EXCEPTION) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gExceptionHandlers[InterruptType] = InterruptHandler;
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+VOID
+EFIAPI
+DefaultSWIExceptionHandler(
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ return;
+}
+
+
+VOID
+EFIAPI
+DefaultExceptionHandler(
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextArm->PC));
+ ASSERT (FALSE);
+
+ return;
+}
+
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+ UINTN Offset;
+ UINTN Length;
+ UINTN Index;
+ BOOLEAN Enabled;
+
+ //
+ // Disable interrupts
+ //
+ Cpu->GetInterruptState (Cpu, &Enabled);
+ Cpu->DisableInterrupt (Cpu);
+
+ //
+ // Initialize the C entry points for interrupts
+ //
+ for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {
+ if (Index == EXCEPT_ARM_SOFTWARE_INTERRUPT) {
+ Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultSWIExceptionHandler);
+ } else {
+ Status = Cpu->RegisterInterruptHandler (Cpu, Index, DefaultExceptionHandler);
+ }
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
+ // Copy an implementation of the ARM exception vectors to 0x0.
+ //
+ Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;
+
+ CopyMem ((VOID *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress), (VOID *)ExceptionHandlersStart, Length);
+
+ //
+ // Patch in the common Assembly exception handler
+ //
+ Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;
+ *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;
+
+ //
+ // Flush Caches since we updated executable stuff
+ //
+ InvalidateInstructionCache ();
+
+ if (Enabled) {
+ //
+ // Restore interrupt state
+ //
+ Status = Cpu->EnableInterrupt (Cpu);
+ }
+
+ return Status;
+}
+
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ WriteBackInvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ InvalidateDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeWriteBack) {
+ WriteBackDataCacheRange((VOID *)(UINTN)Start, (UINTN)Length);
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S new file mode 100755 index 0000000000..d864759afd --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.S @@ -0,0 +1,158 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2008-2009 Apple Inc. All rights reserved. +# +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#------------------------------------------------------------------------------ + +.text +.align 2 + +.globl _ExceptionHandlersStart +.globl _ExceptionHandlersEnd +.globl _CommonExceptionEntry +.globl _AsmCommonExceptionEntry +.globl _gExceptionHandlers + +_ExceptionHandlersStart: + +_Reset: + b _ResetEntry + +_UndefinedInstruction: + b _UndefinedInstructionEntry + +_SoftwareInterrupt: + b _SoftwareInterruptEntry + +_PrefetchAbort: + b _PrefetchAbortEntry + +_DataAbort: + b _DataAbortEntry + +_ReservedException: + b _ReservedExceptionEntry + +_Irq: + b _IrqEntry + +_Fiq: + b _FiqEntry + +_ResetEntry: + stmfd sp!,{r0-r1} + mov r0,#0 + ldr r1,_CommonExceptionEntry + bx r1 + +_UndefinedInstructionEntry: + stmfd sp!,{r0-r1} + mov r0,#1 + ldr r1,_CommonExceptionEntry + bx r1 + +_SoftwareInterruptEntry: + stmfd sp!,{r0-r1} + mov r0,#2 + ldr r1,_CommonExceptionEntry + bx r1 + +_PrefetchAbortEntry: + stmfd sp!,{r0-r1} + mov r0,#3 + sub lr,lr,#4 + ldr r1,_CommonExceptionEntry + bx r1 + +_DataAbortEntry: + stmfd sp!,{r0-r1} + mov r0,#4 + sub lr,lr,#8 + ldr r1,_CommonExceptionEntry + bx r1 + +_ReservedExceptionEntry: + stmfd sp!,{r0-r1} + mov r0,#5 + ldr r1,_CommonExceptionEntry + bx r1 + +_IrqEntry: + stmfd sp!,{r0-r1} + mov r0,#6 + sub lr,lr,#4 + ldr r1,_CommonExceptionEntry + bx r1 + +_FiqEntry: + stmfd sp!,{r0-r1} + mov r0,#7 + sub lr,lr,#4 + ldr r1,_CommonExceptionEntry + bx r1 + +_CommonExceptionEntry: + .byte 0x12 + .byte 0x34 + .byte 0x56 + .byte 0x78 + +_ExceptionHandlersEnd: + +LIndirectgExceptionHandlers: + .long _gExceptionHandlers + +_AsmCommonExceptionEntry: + mrc p15, 0, r1, c6, c0, 2 @ Read IFAR + stmfd sp!,{r1} @ Store the IFAR + + mrc p15, 0, r1, c5, c0, 1 @ Read IFSR + stmfd sp!,{r1} @ Store the IFSR + + mrc p15, 0, r1, c6, c0, 0 @ Read DFAR + stmfd sp!,{r1} @ Store the DFAR + + mrc p15, 0, r1, c5, c0, 0 @ Read DFSR + stmfd sp!,{r1} @ Store the DFSR + + mrs r1,spsr @ Read SPSR (which is the pre-exception CPSR) + stmfd sp!,{r1} @ Store the SPSR + + stmfd sp!,{lr} @ Store the link register (which is the pre-exception PC) + stmfd sp,{sp,lr}^ @ Store user/system mode stack pointer and link register + nop @ Required by ARM architecture + sub sp,sp,#0x08 @ Adjust stack pointer + stmfd sp!,{r2-r12} @ Store general purpose registers + + ldr r3,[sp,#0x40] @ Read saved R1 from the stack (it was saved by the exception entry routine) + ldr r2,[sp,#0x3C] @ Read saved R0 from the stack (it was saved by the exception entry routine) + stmfd sp!,{r2-r3} @ Store general purpose registers R0 and R1 + + mov r1,sp @ Prepare System Context pointer as an argument for the exception handler + + ldr r2,LIndirectgExceptionHandlers @ Offset to 32-bit address of exception handler + ldr r2,[r2] @ Load exception handler table + ldr r3,[r2,r0,lsl #2] @ Index to find the handler for this exception + +// blx r3 @ Call exception handler + bx r3 @ Call exception handler + + ldr r2,[sp,#0x40] @ Load CPSR from context, in case it has changed + msr SPSR_cxsf,r2 @ Store it back to the SPSR to be restored when exiting this handler + + ldmfd sp!,{r0-r12} @ Restore general purpose registers + ldmia sp,{sp,lr}^ @ Restore user/system mode stack pointer and link register + nop @ Required by ARM architecture + add sp,sp,#0x08 @ Adjust stack pointer + ldmfd sp!,{lr} @ Restore the link register (which is the pre-exception PC) + add sp,sp,#0x1C @ Clear out the remaining stack space + movs pc,lr @ Return from exception + diff --git a/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm new file mode 100755 index 0000000000..b91639d149 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/Arm/Exceptions.asm @@ -0,0 +1,152 @@ +//------------------------------------------------------------------------------ +// +// Copyright (c) 2008-2009 Apple Inc. All rights reserved. +// +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +//------------------------------------------------------------------------------ + + EXPORT ExceptionHandlersStart + EXPORT ExceptionHandlersEnd + EXPORT CommonExceptionEntry + EXPORT AsmCommonExceptionEntry + IMPORT gExceptionHandlers + + AREA DxeExceptionHandlers, CODE, READONLY + +ExceptionHandlersStart + +Reset + B ResetEntry + +UndefinedInstruction + B UndefinedInstructionEntry + +SoftwareInterrupt + B SoftwareInterruptEntry + +PrefetchAbort + B PrefetchAbortEntry + +DataAbort + B DataAbortEntry + +ReservedException + B ReservedExceptionEntry + +Irq + B IrqEntry + +Fiq + B FiqEntry + +ResetEntry + STMFD SP!,{R0-R1} + MOV R0,#0 + LDR R1,CommonExceptionEntry + BX R1 + +UndefinedInstructionEntry + STMFD SP!,{R0-R1} + MOV R0,#1 + LDR R1,CommonExceptionEntry + BX R1 + +SoftwareInterruptEntry + STMFD SP!,{R0-R1} + MOV R0,#2 + LDR R1,CommonExceptionEntry + BX R1 + +PrefetchAbortEntry + STMFD SP!,{R0-R1} + MOV R0,#3 + SUB LR,LR,#4 + LDR R1,CommonExceptionEntry + BX R1 + +DataAbortEntry + STMFD SP!,{R0-R1} + MOV R0,#4 + SUB LR,LR,#8 + LDR R1,CommonExceptionEntry + BX R1 + +ReservedExceptionEntry + STMFD SP!,{R0-R1} + MOV R0,#5 + LDR R1,CommonExceptionEntry + BX R1 + +IrqEntry + STMFD SP!,{R0-R1} + MOV R0,#6 + SUB LR,LR,#4 + LDR R1,CommonExceptionEntry + BX R1 + +FiqEntry + STMFD SP!,{R0-R1} + MOV R0,#7 + SUB LR,LR,#4 + LDR R1,CommonExceptionEntry + BX R1 + +CommonExceptionEntry + DCD 0x12345678 + +ExceptionHandlersEnd + +AsmCommonExceptionEntry + MRC p15, 0, r1, c6, c0, 2 ; Read IFAR + STMFD SP!,{R1} ; Store the IFAR + + MRC p15, 0, r1, c5, c0, 1 ; Read IFSR + STMFD SP!,{R1} ; Store the IFSR + + MRC p15, 0, r1, c6, c0, 0 ; Read DFAR + STMFD SP!,{R1} ; Store the DFAR + + MRC p15, 0, r1, c5, c0, 0 ; Read DFSR + STMFD SP!,{R1} ; Store the DFSR + + MRS R1,SPSR ; Read SPSR (which is the pre-exception CPSR) + STMFD SP!,{R1} ; Store the SPSR + + STMFD SP!,{LR} ; Store the link register (which is the pre-exception PC) + STMFD SP,{SP,LR}^ ; Store user/system mode stack pointer and link register + NOP ; Required by ARM architecture + SUB SP,SP,#0x08 ; Adjust stack pointer + STMFD SP!,{R2-R12} ; Store general purpose registers + + LDR R3,[SP,#0x40] ; Read saved R1 from the stack (it was saved by the exception entry routine) + LDR R2,[SP,#0x3C] ; Read saved R0 from the stack (it was saved by the exception entry routine) + STMFD SP!,{R2-R3} ; Store general purpose registers R0 and R1 + + MOV R1,SP ; Prepare System Context pointer as an argument for the exception handler + + LDR R2,=gExceptionHandlers ; Load exception handler table + LDR R3,[R2,R0,LSL #2] ; Index to find the handler for this exception + + BLX R3 ; Call exception handler + + LDR R2,[SP,#0x40] ; Load CPSR from context, in case it has changed + MSR SPSR_cxsf,R2 ; Store it back to the SPSR to be restored when exiting this handler + + LDMFD SP!,{R0-R12} ; Restore general purpose registers + LDM SP,{SP,LR}^ ; Restore user/system mode stack pointer and link register + NOP ; Required by ARM architecture + ADD SP,SP,#0x08 ; Adjust stack pointer + LDMFD SP!,{LR} ; Restore the link register (which is the pre-exception PC) + ADD SP,SP,#0x1C ; Clear out the remaining stack space + MOVS PC,LR ; Return from exception + + END + + diff --git a/EmbeddedPkg/TemplateCpuDxe/CpuDxe.c b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.c new file mode 100644 index 0000000000..90bf8a9af8 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.c @@ -0,0 +1,323 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CpuDxe.h"
+
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuFlushCpuDataCache (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ return FlushCpuDataCache (Start, Length, FlushType);
+}
+
+
+/**
+ This function enables interrupt processing by the processor.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are enabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuEnableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+{
+ EnableInterrupts ();
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function disables interrupt processing by the processor.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Interrupts are disabled on the processor.
+ @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuDisableInterrupt (
+ IN EFI_CPU_ARCH_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+ Disables CPU interrupts.
+
+Arguments:
+ This - Protocol instance structure
+
+Returns:
+ EFI_SUCCESS - If interrupts were disabled in the CPU.
+ EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU.
+
+--*/
+{
+ DisableInterrupts ();
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function retrieves the processor's current interrupt state a returns it in
+ State. If interrupts are currently enabled, then TRUE is returned. If interrupts
+ are currently disabled, then FALSE is returned.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param State A pointer to the processor's current interrupt state. Set to TRUE if
+ interrupts are enabled and FALSE if interrupts are disabled.
+
+ @retval EFI_SUCCESS The processor's current interrupt state was returned in State.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetInterruptState (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ OUT BOOLEAN *State
+ )
+{
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *State = GetInterruptState ();
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function generates an INIT on the processor. If this function succeeds, then the
+ processor will be reset, and control will not be returned to the caller. If InitType is
+ not supported by this processor, or the processor cannot programmatically generate an
+ INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
+ occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InitType The type of processor INIT to perform.
+
+ @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
+ @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported
+ by this processor.
+ @retval EFI_DEVICE_ERROR The processor INIT failed.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuInit (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_CPU_INIT_TYPE InitType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuRegisterInterruptHandler (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ return RegisterInterruptHandler (InterruptType, InterruptHandler);
+}
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuGetTimerValue (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ return GetTimerValue (TimerIndex, TimerValue, TimerPeriod);
+}
+
+
+/**
+ This function modifies the attributes for the memory region specified by BaseAddress and
+ Length from their current attributes to the attributes specified by Attributes.
+
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.
+ @param BaseAddress The physical address that is the start address of a memory region.
+ @param Length The size in bytes of the memory region.
+ @param Attributes The bit mask of attributes to set for the memory region.
+
+ @retval EFI_SUCCESS The attributes were set for the memory region.
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
+ BaseAddress and Length cannot be modified.
+ @retval EFI_INVALID_PARAMETER Length is zero.
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
+ the memory resource range.
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
+ resource range specified by BaseAddress and Length.
+ The bit mask of attributes is not support for the memory resource
+ range specified by BaseAddress and Length.
+
+**/
+EFI_STATUS
+EFIAPI
+CpuSetMemoryAttributes (
+ IN EFI_CPU_ARCH_PROTOCOL *This,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT64 Attributes
+ )
+{
+ //
+ // This is used to set cachability via the MMU on ARM
+ //
+ // This more about optimization and we can usually run fine if the default
+ // settings for cachability are good.
+ //
+ return EFI_UNSUPPORTED;
+}
+
+
+
+
+//
+// Globals used to initialize the protocol
+//
+EFI_HANDLE mCpuHandle = NULL;
+EFI_CPU_ARCH_PROTOCOL mCpu = {
+ CpuFlushCpuDataCache,
+ CpuEnableInterrupt,
+ CpuDisableInterrupt,
+ CpuGetInterruptState,
+ CpuInit,
+ CpuRegisterInterruptHandler,
+ CpuGetTimerValue,
+ CpuSetMemoryAttributes,
+ 0, // NumberOfTimers
+ 4, // DmaBufferAlignment
+};
+
+
+/**
+ Initialize the state information for the CPU Architectural Protocol
+
+ @param ImageHandle of the loaded driver
+ @param SystemTable Pointer to the System Table
+
+ @retval EFI_SUCCESS Protocol registered
+ @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
+ @retval EFI_DEVICE_ERROR Hardware problems
+
+**/
+EFI_STATUS
+CpuDxeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ InitializeExceptions (&mCpu);
+
+ //
+ // Install CPU Architectural Protocol and the thunk protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mCpuHandle,
+ &gEfiCpuArchProtocolGuid, &mCpu,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/CpuDxe.h b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.h new file mode 100644 index 0000000000..c81d8012f8 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/CpuDxe.h @@ -0,0 +1,124 @@ +/** @file
+
+ Copyright (c) 2006 - 2008, Intel Corporation <BR>
+ Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/DebugSupport.h>
+
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+RegisterInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ );
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ );
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+GetTimerValue (
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ );
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ );
+
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c b/EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c new file mode 100644 index 0000000000..5ba38e1623 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/IA32/Exception.c @@ -0,0 +1,183 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <CpuDxe.h>
+
+
+EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100];
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+RegisterInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType > 0xFF) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gExceptionHandlers[InterruptType] = InterruptHandler;
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+VOID
+EFIAPI
+DefaultExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextIa32->Eip));
+ ASSERT (FALSE);
+
+ return;
+}
+
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ )
+{
+ // You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler()
+ // and write all the assembly to handle the interrupts.
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex == 0) {
+ *TimerValue = AsmReadTsc ();
+ if (TimerPeriod != NULL) {
+ //
+ // BugBug: Hard coded. Don't know how to do this generically
+ //
+ *TimerPeriod = 1000000000;
+ }
+ return EFI_SUCCESS;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ AsmInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+
+
diff --git a/EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf b/EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf new file mode 100644 index 0000000000..67d3edc7c4 --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/TemplateCpuDxe.inf @@ -0,0 +1,71 @@ +#%HEADER%
+#/** @file
+#
+# Component discription file for Bds module
+#
+# Copyright (c) 2008, Intel Corporation. <BR>
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TemplateCpuDxe
+ FILE_GUID = CB6DC1E4-5B27-41E8-BC27-9AA50B62081E
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = CpuDxeInitialize
+
+
+[Sources.common]
+ CpuDxe.c
+
+[Sources.ARM]
+ Arm/Exception.c
+ Arm/Exceptions.asm
+ Arm/Exceptions.S
+
+[Sources.IA32]
+ IA32/Exception.c
+
+[Sources.X64]
+ X64/Exception.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[Packages.ARM]
+ ArmPkg/ArmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiRuntimeServicesTableLib
+ ReportStatusCodeLib
+ PerformanceLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ UefiDriverEntryPoint
+ CacheMaintenanceLib
+
+[Protocols]
+ gEfiCpuArchProtocolGuid
+
+[Pcd.ARM]
+ gArmTokenSpaceGuid.PcdCpuVectorBaseAddress
+
+
+[depex]
+ TRUE
diff --git a/EmbeddedPkg/TemplateCpuDxe/X64/Exception.c b/EmbeddedPkg/TemplateCpuDxe/X64/Exception.c new file mode 100644 index 0000000000..f86eda077a --- /dev/null +++ b/EmbeddedPkg/TemplateCpuDxe/X64/Exception.c @@ -0,0 +1,183 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <CpuDxe.h>
+
+
+EFI_EXCEPTION_CALLBACK gExceptionHandlers[0x100];
+
+
+/**
+ This function registers and enables the handler specified by InterruptHandler for a processor
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
+ The installed handler is called once for each processor interrupt or exception.
+
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
+ are enabled and FALSE if interrupts are disabled.
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
+ when a processor interrupt occurs. If this parameter is NULL, then the handler
+ will be uninstalled.
+
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
+ previously installed.
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
+ previously installed.
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
+
+**/
+EFI_STATUS
+RegisterInterruptHandler (
+ IN EFI_EXCEPTION_TYPE InterruptType,
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
+ )
+{
+ if (InterruptType > 0xFF) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((InterruptHandler == NULL) && (gExceptionHandlers[InterruptType] == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gExceptionHandlers[InterruptType] = InterruptHandler;
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+VOID
+EFIAPI
+DefaultExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ DEBUG ((EFI_D_ERROR, "Exception %d from %x\n", ExceptionType, SystemContext.SystemContextX64->Rip));
+ ASSERT (FALSE);
+
+ return;
+}
+
+
+
+EFI_STATUS
+InitializeExceptions (
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu
+ )
+{
+ // You need to initialize gExceptionHandlers[] to point to DefaultExceptionHandler()
+ // and write all the assembly to handle the interrupts.
+ ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
+}
+
+
+
+/**
+ This function reads the processor timer specified by TimerIndex and returns it in TimerValue.
+
+ @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter
+ must be between 0 and NumberOfTimers-1.
+ @param TimerValue Pointer to the returned timer value.
+ @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment
+ of TimerValue.
+
+ @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue.
+ @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers.
+ @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid.
+ @retval EFI_UNSUPPORTED The processor does not have any readable timers.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTimerValue (
+ IN UINT32 TimerIndex,
+ OUT UINT64 *TimerValue,
+ OUT UINT64 *TimerPeriod OPTIONAL
+ )
+{
+ if (TimerValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TimerIndex == 0) {
+ *TimerValue = AsmReadTsc ();
+ if (TimerPeriod != NULL) {
+ //
+ // BugBug: Hard coded. Don't know how to do this generically
+ //
+ *TimerPeriod = 1000000000;
+ }
+ return EFI_SUCCESS;
+ }
+ return EFI_INVALID_PARAMETER;
+}
+
+
+/**
+ This function flushes the range of addresses from Start to Start+Length
+ from the processor's data cache. If Start is not aligned to a cache line
+ boundary, then the bytes before Start to the preceding cache line boundary
+ are also flushed. If Start+Length is not aligned to a cache line boundary,
+ then the bytes past Start+Length to the end of the next cache line boundary
+ are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
+ supported. If the data cache is fully coherent with all DMA operations, then
+ this function can just return EFI_SUCCESS. If the processor does not support
+ flushing a range of the data cache, then the entire data cache can be flushed.
+
+ @param Start The beginning physical address to flush from the processor's data
+ cache.
+ @param Length The number of bytes to flush from the processor's data cache. This
+ function may flush more bytes than Length specifies depending upon
+ the granularity of the flush operation that the processor supports.
+ @param FlushType Specifies the type of flush operation to perform.
+
+ @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
+ the processor's data cache.
+ @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
+ by FlushType.
+ @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
+ from the processor's data cache.
+
+**/
+EFI_STATUS
+EFIAPI
+FlushCpuDataCache (
+ IN EFI_PHYSICAL_ADDRESS Start,
+ IN UINT64 Length,
+ IN EFI_CPU_FLUSH_TYPE FlushType
+ )
+{
+ if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {
+ AsmWbinvd ();
+ return EFI_SUCCESS;
+ } else if (FlushType == EfiCpuFlushTypeInvalidate) {
+ AsmInvd ();
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+
+
+
diff --git a/EmbeddedPkg/TemplateMetronomeDxe/Metronome.c b/EmbeddedPkg/TemplateMetronomeDxe/Metronome.c new file mode 100644 index 0000000000..861bf249cd --- /dev/null +++ b/EmbeddedPkg/TemplateMetronomeDxe/Metronome.c @@ -0,0 +1,132 @@ +/** @file
+
+ Copyright (c) 2008-2009, Apple Inc. All rights reserved.
+
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiDxe.h>
+
+#include <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/TimerLib.h>
+
+#include <Protocol/Metronome.h>
+
+
+
+/**
+ The WaitForTick() function waits for the number of ticks specified by
+ TickNumber from a known time source in the platform. If TickNumber of
+ ticks are detected, then EFI_SUCCESS is returned. The actual time passed
+ between entry of this function and the first tick is between 0 and
+ TickPeriod 100 nS units. If you want to guarantee that at least TickPeriod
+ time has elapsed, wait for two ticks. This function waits for a hardware
+ event to determine when a tick occurs. It is possible for interrupt
+ processing, or exception processing to interrupt the execution of the
+ WaitForTick() function. Depending on the hardware source for the ticks, it
+ is possible for a tick to be missed. This function cannot guarantee that
+ ticks will not be missed. If a timeout occurs waiting for the specified
+ number of ticks, then EFI_TIMEOUT is returned.
+
+ @param This The EFI_METRONOME_ARCH_PROTOCOL instance.
+ @param TickNumber Number of ticks to wait.
+
+ @retval EFI_SUCCESS The wait for the number of ticks specified by TickNumber
+ succeeded.
+ @retval EFI_TIMEOUT A timeout occurred waiting for the specified number of ticks.
+
+**/
+EFI_STATUS
+EFIAPI
+WaitForTick (
+ IN EFI_METRONOME_ARCH_PROTOCOL *This,
+ IN UINT32 TickNumber
+ )
+{
+ //
+ // Fill me in
+ //
+ MicroSecondDelay (10 * TickNumber);
+ return EFI_UNSUPPORTED;
+}
+
+
+
+/**
+ Interface stucture for the Metronome Architectural Protocol.
+
+ @par Protocol Description:
+ This protocol provides access to a known time source in the platform to the
+ core. The core uses this known time source to produce core services that
+ require calibrated delays.
+
+ @param WaitForTick
+ Waits for a specified number of ticks from a known time source
+ in the platform. The actual time passed between entry of this
+ function and the first tick is between 0 and TickPeriod 100 nS
+ units. If you want to guarantee that at least TickPeriod time
+ has elapsed, wait for two ticks.
+
+ @param TickPeriod
+ The period of platform's known time source in 100 nS units.
+ This value on any platform must be at least 10 uS, and must not
+ exceed 200 uS. The value in this field is a constant that must
+ not be modified after the Metronome architectural protocol is
+ installed. All consumers must treat this as a read-only field.
+
+**/
+EFI_METRONOME_ARCH_PROTOCOL gMetronome = {
+ WaitForTick,
+ 100
+};
+
+
+EFI_HANDLE gMetronomeHandle = NULL;
+
+
+
+/**
+ 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
+MetronomeInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Do any hardware init required to make WaitForTick () to work here.
+ //
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &gMetronomeHandle,
+ &gEfiMetronomeArchProtocolGuid, &gMetronome,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git a/EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf b/EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf new file mode 100644 index 0000000000..9a4e53a703 --- /dev/null +++ b/EmbeddedPkg/TemplateMetronomeDxe/TemplateMetronomeDxe.inf @@ -0,0 +1,50 @@ +#%HEADER%
+#/** @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 = TemplateMetronomeDxe
+ FILE_GUID = 4C6E0267-C77D-410D-8100-1495911A989D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = MetronomeInitialize
+
+
+[Sources.common]
+ Metronome.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiLib
+ UefiBootServicesTableLib
+ DebugLib
+ PrintLib
+ UefiDriverEntryPoint
+ TimerLib
+
+[Guids]
+
+
+[Protocols]
+ gEfiMetronomeArchProtocolGuid
+
+[depex]
+ TRUE
diff --git a/EmbeddedPkg/TemplateSec/TemplateSec.c b/EmbeddedPkg/TemplateSec/TemplateSec.c new file mode 100644 index 0000000000..dbbf3cb815 --- /dev/null +++ b/EmbeddedPkg/TemplateSec/TemplateSec.c @@ -0,0 +1,76 @@ +/** @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/DebugLib.h>
+#include <Library/PrePiLib.h>
+#include <Library/PcdLib.h>
+
+#include <Ppi/GuidedSectionExtraction.h>
+
+VOID
+_ModuleEntryPoint (
+ VOID
+ )
+{
+}
+
+VOID
+CEntryPoint (
+ VOID *MemoryBase,
+ UINTN MemorySize,
+ VOID *StackBase,
+ UINTN StackSize
+ )
+{
+ EFI_PHYSICAL_ADDRESS MemoryBegin;
+ UINT64 MemoryLength;
+ VOID *HobBase;
+
+ //
+ // Boot strap the C environment so the other library services will work properly.
+ //
+ MemoryBegin = (EFI_PHYSICAL_ADDRESS)(UINTN)MemoryBase;
+ MemoryLength = (UINT64)MemorySize;
+ HobBase = (VOID *)(UINTN)(FixedPcdGet32(PcdEmbeddedFdBaseAddress) + FixedPcdGet32(PcdEmbeddedFdSize));
+ CreateHobList (MemoryBase, MemorySize, HobBase, StackBase);
+
+ MemoryBegin = (EFI_PHYSICAL_ADDRESS)(UINTN)StackBase;
+ MemoryLength = (UINT64)StackSize;
+ UpdateStackHob (MemoryBegin, MemoryLength);
+
+ DEBUG ((DEBUG_ERROR, "CEntryPoint (%x,%x,%x,%x)\n", MemoryBase, MemorySize, StackBase, StackSize));
+
+ //
+ // Add your C code stuff here....
+ //
+
+
+ //
+ // Load the DXE Core and transfer control to it
+ //
+
+ // Give the DXE Core access to our DEBUG and ASSERT infrastructure so this will work prior
+ // to the DXE version being loaded. Thus we close the debugging gap between phases.
+ AddDxeCoreReportStatusCodeCallback ();
+
+ //BuildFvHobs (PcdBfvBase, PcdBfvSize, NULL);
+
+ LoadDxeCoreFromFv (NULL, 0);
+
+ // DXE Core should always load and never return
+ ASSERT (FALSE);
+}
+
diff --git a/EmbeddedPkg/TemplateSec/TemplateSec.inf b/EmbeddedPkg/TemplateSec/TemplateSec.inf new file mode 100644 index 0000000000..5c62b7520e --- /dev/null +++ b/EmbeddedPkg/TemplateSec/TemplateSec.inf @@ -0,0 +1,66 @@ +#%HEADER% +#/** @file +# +# Component description file for DxeIpl module +# +# The responsibility of this module is to load the DXE Core from a Firmware Volume. This implementation i used to load a 32-bit DXE Core. +# +# Copyright (c) 2006 - 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 = TemplateSec + FILE_GUID = 1D6F730F-5A55-4078-869B-E0A18324BDC8 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 ARM +# + +[Sources.common] + TemplateSec.c + +[Sources.Ia32] +# Ia32/ResetVector.asm | MSFT +# Ia32/ResetVector.S | GCC + +[Sources.X64] +# X64/ResetVector.asm | MSFT +# X64/ResetVector.S | GCC + +[Sources.ARM] +# Arm/ResetVector.asm | RVCT +# Arm/ResetVector.S | GCC + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + UefiDecompressLib + PeCoffLib + CacheMaintenanceLib + PrePiLib + +[Pcd] + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdBaseAddress + gEmbeddedTokenSpaceGuid.PcdEmbeddedFdSize + diff --git a/EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf b/EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf new file mode 100644 index 0000000000..d7c1f05674 --- /dev/null +++ b/EmbeddedPkg/TemplateTimerDxe/TemplateTimerDxe.inf @@ -0,0 +1,56 @@ +#%HEADER%
+#/** @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
\ No newline at end of file diff --git a/EmbeddedPkg/TemplateTimerDxe/Timer.c b/EmbeddedPkg/TemplateTimerDxe/Timer.c new file mode 100644 index 0000000000..4bfa3e8622 --- /dev/null +++ b/EmbeddedPkg/TemplateTimerDxe/Timer.c @@ -0,0 +1,373 @@ +/** @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;
+
+ // Mask all interrupts
+ 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;
+}
+
|